Skip to content

feat(core): tuple and typed-array interop for GPU and three.js - #202

Merged
pbroom merged 5 commits into
mainfrom
feat/array-interop
Oct 10, 2026
Merged

pbroom merged 5 commits into
mainfrom
feat/array-interop

Conversation

@pbroom

@pbroom pbroom commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner

Stack 3/4. New interop module (root + color-kit/interop): to<Space>Array(color, out?, offset, { clamp? }) / *Array4 writers, from<Space>Array readers for linearSrgb, srgb, linearP3, p3, oklab, oklch; packColors/unpackColors for GPU buffers (stride/offset, WGSL vec3 padding).

  • Unclamped floats by default; gamut mapping by composition (toLinearSrgbArray(toSrgbGamut(c))).
  • colorjs.io agreement ≤ 7e-15. Float32 < 1e-5 ΔE_OK in gamut.
  • three.js (r186, devDependency tests): new Color().fromArray(toLinearSrgbArray(c)) is exact and unclamped; setStyle(toCss(c)) quantizes to 8-bit and clips.
  • Size: toLinearSrgbArray 617 B gzip; pack+unpack 2.3 kB; everyday import unchanged. New size budgets.

Recommendation: adopt in addition — toRgb/toP3/toCss stay for UI/CSS; arrays for GPU/three.js/HDR.

🤖 Generated with Claude Code

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-25T22:25:57.014348Z fb19a6d PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

pbroom commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@greptile-apps

greptile-apps Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 4/5

[Medium risk] Adds array conversion functions for GPU and graphics libraries.

The PR appears safe to merge, with a non-blocking gap in validation of its new TypeScript overloads.

Fix All in CursorFindings

  1. P2 Type checks never run ▶

Summary

The PR adds tuple writers and readers for six color spaces, strided GPU-buffer packing, root and subpath exports, and three.js interop tests. The API wiring appears consistent; its new compile-time overload checks need to be included in validation.

Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Color[OKLCH Color] --> Writers[Array writers]
  Color --> Pack[packColors]
  Writers --> Buffer[Tuple or typed array]
  Pack --> Buffer
  Buffer --> Readers[Array readers]
  Buffer --> Unpack[unpackColors]
  Readers --> Color
  Unpack --> Color
Loading

Reviews (1) · Last reviewed commit: "fix(core): type packColors as Float32Arr..."

Comment thread packages/core/src/interop/interop.typecheck.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fb19a6df41

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/core/src/interop/pack.ts

pbroom commented Oct 10, 2026 •

Copy link
Copy Markdown
Owner Author

Merge activity

  • Oct 10, 6:47 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Oct 10, 6:51 PM UTC: Graphite rebased this pull request as part of a merge.
  • Oct 10, 6:51 PM UTC: @pbroom merged this pull request with Graphite.

@pbroom
pbroom changed the base branch from feat/out-variants to graphite-base/202 October 10, 2026 18:48
pbroom added a commit that referenced this pull request Oct 10, 2026
Stack 2/4. Adds `out`-first, allocation-free `*Into` variants (conversions, low-level kernels, `mixInto`/`interpolateInto`, `toSrgbGamutInto`/`toP3GamutInto`). Allocating APIs become thin wrappers over the kernels — bit-identical (0 mismatches, 100k inputs × 30 functions).

- `bench:into`: Into variants ~0 B/op, 0 GCs per 1e6 ops (vs up to 28); ns/op roughly equal.
- Side benefit: existing gamut mapping 20–28% faster, `toRgb`/`toP3` allocate 1 object instead of 4.
- A React ColorPlane CPU-loop dogfood was measured and **dropped**: fewer GCs but clamp paths 8–10% slower (V8 boxes doubles in object fields).

**Recommendation: adopt in addition** — object API stays primary; Into reduces GC count, not time. Typed arrays (#202) are the better zero-alloc per-pixel target.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@pbroom
pbroom changed the base branch from graphite-base/202 to main October 10, 2026 18:49
pbroom and others added 5 commits October 10, 2026 18:50
Add a `color-kit/interop` module (also exported from the root) with
allocation-free array writers and readers for linearSrgb, srgb, linearP3,
p3, oklab and oklch, `*Array4` variants that carry alpha, and
`packColors`/`unpackColors` for strided GPU buffers.

Writers emit unclamped floats by default (matching three.js and HDR
pipelines); `clamp` clips RGB channels and `gamutMap` reuses
toSrgbGamut/toP3Gamut. Exports `ColorTuple`/`ColorTuple4`.

Tests cover round trips, offset/stride math, Float32Array precision,
clamp/gamutMap, colorjs.io agreement for every space, and the three.js
`Color.fromArray` recipe against the real `three` package (devDependency).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…omposition

The option pulled the gamut-mapping solver (~1 kB gzip) into every array
writer. Callers now compose instead: `toLinearSrgbArray(toSrgbGamut(c), out)`
or `packColors(colors.map(toSrgbGamut), space)`. `clamp` stays.

toLinearSrgbArray drops from 1.62 kB to 617 B gzip; packColors +
unpackColors from 2.73 kB to 2.23 kB. Size budgets lowered to ~15% above.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Split packColors into overloads: no `out` (or `undefined`) returns
`Float32Array`, and a provided `out` returns its own type. Previously an
explicit `undefined` with options inferred `WritableArrayLike`, so
`.subarray` did not type-check. Locked in interop.typecheck.ts.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Nothing ran tsc over `packages/*/src`: tsup only emits declarations for the
public entries and vitest does not typecheck, so the type-level assertions
in `core/src/interop/interop.typecheck.ts`,
`core/src/plane/define-plane.typecheck.ts` and
`driver/src/color-input.typecheck.ts` were never checked.

Add a `typecheck` script (`tsc --noEmit`) to core and driver, a root
`pnpm typecheck` that runs it recursively, and a CI step in the
build-and-test job. Verified that removing a `@ts-expect-error` in either
core file makes `pnpm typecheck` fail.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Passing `out: T | undefined` (for example a lazily created
`Float32Array | undefined` scratch buffer) to `packColors` or any
`to*Array` writer failed with TS2769, because the split overloads only
accepted `undefined` or `T`. Add a third overload per function that takes
`T | undefined` and returns exactly `T | Float32Array` (packColors) or
`T | ColorTuple` / `T | ColorTuple4` (writers).

interop.typecheck.ts now asserts the exact result types with an `Equal`
helper for the union, absent and present cases. Without the new overloads
those assertions fail to compile.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@pbroom
pbroom force-pushed the feat/array-interop branch from 1b6a929 to 626c845 Compare October 10, 2026 18:50
@vercel

vercel Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
color-kit Ready Ready Preview Oct 10, 2026 6:52pm UTC

@pbroom
pbroom merged commit d60010d into main Oct 10, 2026
6 of 7 checks passed
@pbroom
pbroom deleted the feat/array-interop branch October 10, 2026 18:51
pbroom added a commit that referenced this pull request Oct 10, 2026
Stack 4/4. New guide at `/docs/guides/graphics-and-performance` (new Guides nav section) demonstrating #200–#202 with live demos, API examples, comparisons to existing APIs and pmndrs/math, and adopt-in-addition vs replace recommendations.

- Linear-mix demo: pickers/presets, per-space gradient strips, midpoint hex / OKLab L / Y / out-of-sRGB flag.
- `mixInto` rAF loop with frame counter (reduced-motion aware).
- WebGL2 quad colored via `packColors` (linear vs gamma blending, packed floats shown).
- Code shown is the demo source (`?raw`), demos lazy-loaded per chunk.

Verified in browser: no console errors, interactions work, 375px no horizontal scroll. Docs tsc errors on this branch are only the 4 pre-existing home-route errors fixed by #199.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

This branch was successfully deployed

1 active deployment
Preview — 626c845e Deployed Oct 10, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant