Skip to content

feat: Add immediate variables - #3031

Open
reczkok wants to merge 3 commits into
mainfrom
feat/immediate-var
Open

reczkok wants to merge 3 commits into
mainfrom
feat/immediate-var

Conversation

@reczkok

@reczkok reczkok commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Adds tgpu['~unstable'].immediateVar(schema), a read-only var<immediate> (WebGPU push constants). One per shader, scalars/vectors/matrices/structs only, can fulfill accessors.

Values at draw time come in #3032, stacked on this.

@github-actions

github-actions Bot commented Sep 16, 2026

Copy link
Copy Markdown

pkg.pr.new

packages
Ready to be installed by your favorite package manager ⬇️

https://pkg.pr.new/software-mansion/TypeGPU/eslint-plugin-typegpu@0c7cb1c330f242ecc0333761639922f87109359b
https://pkg.pr.new/software-mansion/TypeGPU/tinyest@0c7cb1c330f242ecc0333761639922f87109359b
https://pkg.pr.new/software-mansion/TypeGPU/tinyest-for-wgsl@0c7cb1c330f242ecc0333761639922f87109359b
https://pkg.pr.new/software-mansion/TypeGPU/typegpu@0c7cb1c330f242ecc0333761639922f87109359b
https://pkg.pr.new/software-mansion/TypeGPU/@typegpu/cli@0c7cb1c330f242ecc0333761639922f87109359b
https://pkg.pr.new/software-mansion/TypeGPU/@typegpu/gl@0c7cb1c330f242ecc0333761639922f87109359b
https://pkg.pr.new/software-mansion/TypeGPU/unplugin-typegpu@0c7cb1c330f242ecc0333761639922f87109359b

benchmark
view benchmark

commit
view commit

@github-actions

github-actions Bot commented Sep 16, 2026

Copy link
Copy Markdown

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.72, 1.35, 2.68, 3.94, 4.73, 8.30, 15.63, 15.91]
  line [0.68, 1.32, 2.76, 4.21, 4.42, 8.70, 16.55, 16.71]
  line [0.64, 1.25, 2.77, 3.92, 4.73, 8.30, 14.85, 15.46]
Loading
---
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.19, 0.36, 0.46, 0.54, 0.77, 0.77, 0.95, 1.05]
  line [0.20, 0.33, 0.48, 0.54, 0.74, 0.81, 0.99, 1.05]
  line [0.18, 0.35, 0.51, 0.54, 0.79, 0.81, 0.95, 1.00]
Loading
---
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.64, 1.62, 3.18, 4.73, 7.72, 17.17, 35.70, 72.00]
  line [0.86, 1.60, 2.47, 4.51, 7.65, 16.96, 35.70, 72.57]
  line [0.68, 1.72, 2.27, 4.37, 7.61, 16.79, 36.07, 72.29]
Loading

@github-actions

github-actions Bot commented Sep 16, 2026

Copy link
Copy Markdown

Bundle size comparison (import * as ... in PR vs import * as ... in target):

🟢 Decreased ➖ Unchanged 🔴 Increased (max 0.86%) ❔ Unknown
0 39 286 0

import * as ... in PR vs import * as ... in target (did bundle size increase?):

Test tsdown
d_ref.ts 5.03 kB ($${\color{red}+0.9\%}$$)
STATIC_tgpu.ts 276.88 kB ($${\color{red}+0.7\%}$$)
STATIC_allImports.ts 302.94 kB ($${\color{red}+0.6\%}$$)

If you wish to run a comparison for other, slower bundlers, run the 'Tree-shake test' from the GitHub Actions menu.

@reczkok
reczkok added this pull request to stack #3033 September 16, 2026 17:20
@reczkok
reczkok marked this pull request as ready for review September 16, 2026 19:58
Copilot AI lite review requested due to automatic review settings September 16, 2026 19:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Four unresolved moderate review comments remain regarding schema validation and public resolution typing.

Pull request overview

Adds unstable immediateVar support for read-only WGSL var<immediate> resources, including resolution, generation, accessors, tests, and documentation.

Changes:

  • Adds immediate-variable validation, tracking, mutation checks, and accessor support.
  • Integrates immediate address spaces with types, origins, exports, and tooling.
  • Adds tests and accessor documentation.
File summaries
File Summary
packages/unplugin-typegpu/src/core/common.ts Registers immediateVar for auto-naming.
packages/typegpu/tests/immediates.test.ts Tests resolution, validation, mutation, and accessors.
packages/typegpu/src/types.ts Adds immediate resolution typing; moderate comment (1 vote) requests inclusion in ResolvableObject.
packages/typegpu/src/tgsl/wgslGenerator.ts Generates immediate address-space variables and rejects mutation.
packages/typegpu/src/tgsl/shaderGenerator.ts Supports immediate variable declarations.
packages/typegpu/src/tgpuUnstable.ts Exports immediateVar.
packages/typegpu/src/resolutionCtx.ts Tracks shader immediates.
packages/typegpu/src/indexNamedExports.ts Exports immediate types and guards.
packages/typegpu/src/data/wgslTypes.ts Adds the immediate address-space type.
packages/typegpu/src/data/snippet.ts Adds immediate origins and pointer metadata.
packages/typegpu/src/core/slot/slotTypes.ts Allows immediates to fulfill accessors.
packages/typegpu/src/core/immediate/immediateVar.ts Implements immediate variables; three moderate comments (1 vote each) cover abstract-struct and abstract-numeric rejection plus ResolvableObject typing.
apps/typegpu-docs/src/content/docs/apis/accessors.mdx Documents immediate accessor usage.
Review details

Suppressed comments (4)

packages/typegpu/src/core/immediate/immediateVar.ts:70

  • isWgslStruct also matches d.abstruct(...), but those schemas are explicitly rejected by resolveStruct as non-resolvable. This branch returns after recursively validating such a schema, so immediateVar(d.abstruct({ value: d.f32 })) is accepted and only fails later during shader resolution; reject abstract structs here.
  if (isWgslStruct(inner)) {

packages/typegpu/src/core/immediate/immediateVar.ts:81

  • isNumericSchema includes abstractInt and abstractFloat, but resolveData cannot represent either in WGSL. Consequently immediateVar(d.abstractFloat) passes this validation and only fails later with abstractFloat has no representation in WGSL, rather than being rejected as an invalid immediate schema; exclude abstract numerics here (including when nested in a struct).
  if (!isNumericSchema(inner) && !isVec(inner) && !isMat(inner)) {

packages/typegpu/src/core/immediate/immediateVar.ts:37

  • TgpuImmediateVar is a resolvable shader resource, but it is not included in the public ResolvableObject union (unlike TgpuVar). Consequently, tgpu.resolve([tgpu['~unstable'].immediateVar(d.f32)]) is rejected by the TypeScript overload even though the runtime resolver can handle it. Add this type to ResolvableObject and cover direct resolution with a type-checked test.
export interface TgpuImmediateVar<TDataType extends BaseData = BaseData> extends TgpuNamable {
  readonly [$internal]: true;
  readonly [$soul]: TgpuImmediateVarSoul<TDataType>;
  readonly resourceType: 'immediate-var';
  readonly dataType: TDataType;

packages/typegpu/src/types.ts:25

  • This type is not added to the ResolvableObject union below (which includes TgpuVar). As a result, TypeScript rejects tgpu.resolve([immediate]) and using an immediate as a resolveWithContext external even though the runtime object is resolvable; add TgpuImmediateVar to that union so the new resource participates in the existing resolve API.
import type { TgpuImmediateVar } from './core/immediate/immediateVar.ts';
  • Files reviewed: 13/13 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes — reviewed the full 13-file diff at bb600d3.

  • New immediateVar resource — adds tgpu['~unstable'].immediateVar(schema), which emits a read-only var<immediate>, exported via tgpuUnstable.ts with an isImmediateVar type guard.
  • Schema validation — accepts concrete scalars/vectors/matrices and structs thereof, recursing into structs; rejects booleans, arrays, atomics, textures, samplers and pointers.
  • Resolution/codegen plumbing — new 'immediate' Origin/AddressSpace, var<immediate> emission via usageToVarTemplateMap, per-resolution single-immediate enforcement in registerImmediate, usedImmediate on ResolutionResult, and mutation rejection for the immediate origin.
  • Accessor integrationTgpuImmediateVar added to the read-only DataAccessorIn union.
  • Unplugin auto-namingimmediateVar added to resourceConstructors.
  • Docs — new accessors.mdx section plus an updated "what can be bound" table row.
  • Tests — new immediates.test.ts (10 cases) covering resolution, single-immediate enforcement, comptime pruning, mutation rejection, schema validation, normal-mode access and accessor fulfillment.

The runtime wiring (pipeline with/setImmediates, root.enabledWgslLanguageFeatures detection) is intentionally deferred to the stacked #3032, so the unused usedImmediate field and the docstring's enabledWgslLanguageFeatures reference are expected at this stage.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

Comment thread packages/typegpu/src/core/immediate/immediateVar.ts Outdated
Comment thread packages/typegpu/src/core/immediate/immediateVar.ts Outdated

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes — incremental review of the delta from bb600d3 to 0c7cb1c (846fdc7 "apply review suggestions" + 0c7cb1c "use inline snapshots in immediates tests"), with full-PR context.

  • Hardened isImmediateVar — replaced the instanceof TgpuImmediateVarImpl check with resourceType === 'immediate-var' && isMarkedInternal(value), matching the cross-runtime guard style used across the codebase.
  • Reject decorated root schemasassertValidImmediateSchema now checks isWgslStruct(schema) directly, rejects a decorated root (d.size(...), d.align(...)) with a dedicated error, and still undecorates struct members before recursing so member-level decorations remain valid.
  • Inline snapshots — immediates tests switched from regex toThrow matchers to toThrowErrorMatchingInlineSnapshot, pinning exact WGSL output and error text, plus a new "rejects decorated schemas" case.
  • Prior feedback addressed — both human review threads (the instanceof fragility and the decorated-value acceptance) are resolved and reflected in these commits.

Verified locally at 0c7cb1c3: npx vitest run tests/immediates.test.ts (11 tests pass) and pnpm --filter typegpu test:types (clean). The deferred runtime wiring (usedImmediate consumption, enabledWgslLanguageFeatures detection) remains intentionally scoped to the stacked #3032.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@aleksanderkatan aleksanderkatan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

yeppers

*
* @param dataType The schema of the held data's type. Cannot contain arrays, atomics or booleans.
*/
export function immediateVar<TDataType extends AnyWgslData>(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we narrow this type to type ImmediateData = ScalarData | VecData | MatData | WgslStruct;?

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.

4 participants