Skip to content

feat(@typegpu/gl): Implicit pointer definitions in GLSL generator - #2819

Open
iwoplaza wants to merge 1 commit into
feat/make-triangle-work-with-gl-fallbackfrom
feat/glsl-implicit-pointer-definitions
Open

feat(@typegpu/gl): Implicit pointer definitions in GLSL generator#2819
iwoplaza wants to merge 1 commit into
feat/make-triangle-work-with-gl-fallbackfrom
feat/glsl-implicit-pointer-definitions

Conversation

@iwoplaza

@iwoplaza iwoplaza commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

Closes #2679

Copilot AI lite review requested due to automatic review settings August 9, 2026 20:35
@github-actions

github-actions Bot commented Aug 9, 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@abec4f86d494968954a7ff1a54c374fdf91d39e8
https://pkg.pr.new/software-mansion/TypeGPU/tgpu-gen@abec4f86d494968954a7ff1a54c374fdf91d39e8
https://pkg.pr.new/software-mansion/TypeGPU/tinyest-for-wgsl@abec4f86d494968954a7ff1a54c374fdf91d39e8
https://pkg.pr.new/software-mansion/TypeGPU/typegpu@abec4f86d494968954a7ff1a54c374fdf91d39e8
https://pkg.pr.new/software-mansion/TypeGPU/@typegpu/cli@abec4f86d494968954a7ff1a54c374fdf91d39e8
https://pkg.pr.new/software-mansion/TypeGPU/@typegpu/color@abec4f86d494968954a7ff1a54c374fdf91d39e8
https://pkg.pr.new/software-mansion/TypeGPU/@typegpu/gl@abec4f86d494968954a7ff1a54c374fdf91d39e8
https://pkg.pr.new/software-mansion/TypeGPU/@typegpu/noise@abec4f86d494968954a7ff1a54c374fdf91d39e8
https://pkg.pr.new/software-mansion/TypeGPU/@typegpu/radiance-cascades@abec4f86d494968954a7ff1a54c374fdf91d39e8
https://pkg.pr.new/software-mansion/TypeGPU/@typegpu/react@abec4f86d494968954a7ff1a54c374fdf91d39e8
https://pkg.pr.new/software-mansion/TypeGPU/@typegpu/sdf@abec4f86d494968954a7ff1a54c374fdf91d39e8
https://pkg.pr.new/software-mansion/TypeGPU/@typegpu/three@abec4f86d494968954a7ff1a54c374fdf91d39e8
https://pkg.pr.new/software-mansion/TypeGPU/unplugin-typegpu@abec4f86d494968954a7ff1a54c374fdf91d39e8

benchmark
view benchmark

commit
view commit

@github-actions

github-actions Bot commented Aug 9, 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.73, 1.33, 2.97, 4.73, 5.39, 8.97, 16.34, 18.83]
  line [0.68, 1.37, 3.24, 4.24, 5.31, 8.89, 17.91, 17.81]
  line [0.80, 1.61, 3.36, 4.87, 5.77, 9.01, 16.89, 20.65]
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.21, 0.40, 0.60, 0.70, 0.97, 0.97, 1.08, 1.21]
  line [0.23, 0.41, 0.52, 0.60, 0.82, 0.87, 1.07, 1.14]
  line [0.20, 0.42, 0.53, 0.65, 0.89, 0.95, 1.21, 1.37]
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.73, 1.84, 3.31, 5.31, 9.58, 20.92, 41.08, 80.11]
  line [0.82, 1.78, 3.62, 4.86, 8.67, 17.23, 38.47, 79.36]
  line [0.88, 1.82, 3.60, 4.96, 9.53, 19.98, 42.81, 86.22]
Loading

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown

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

🟢 Decreased (max -0.28%) ➖ Unchanged 🔴 Increased (max 2.79%) ❔ Unknown
6 129 187 1

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

Test tsdown
std_isBeingTranspiled.ts 15.71 kB ($${\color{red}+2.8\%}$$)
std_getTargetShaderLanguage.ts 15.77 kB ($${\color{red}+2.8\%}$$)
std_getShaderStage.ts 15.76 kB

import { ... } in PR vs import * as ... in PR (is the library tree-Shakeable?):

Test tsdown
tgpu_init.ts 268.11 kB ($${\color{green}-3.3\%}$$)
tgpu_initFromDevice.ts 267.58 kB ($${\color{green}-3.5\%}$$)
tgpu_resolve.ts 168.82 kB ($${\color{green}-39.1\%}$$)
tgpu_resolveWithContext.ts 168.76 kB ($${\color{green}-39.1\%}$$)
tgpu_bindGroupLayout.ts 73.79 kB ($${\color{green}-73.4\%}$$)
tgpu_mutableAccessor.ts 68.52 kB ($${\color{green}-75.3\%}$$)
tgpu_accessor.ts 68.52 kB ($${\color{green}-75.3\%}$$)
tgpu_privateVar.ts 67.21 kB ($${\color{green}-75.8\%}$$)
tgpu_workgroupVar.ts 67.21 kB ($${\color{green}-75.8\%}$$)
tgpu_const.ts 66.63 kB ($${\color{green}-76.0\%}$$)
tgpu_lazy.ts 66.42 kB ($${\color{green}-76.0\%}$$)
tgpu_fragmentFn.ts 38.92 kB ($${\color{green}-86.0\%}$$)
tgpu_fn.ts 38.86 kB ($${\color{green}-86.0\%}$$)
tgpu_vertexFn.ts 38.73 kB ($${\color{green}-86.0\%}$$)
tgpu_computeFn.ts 38.44 kB ($${\color{green}-86.1\%}$$)
tgpu_vertexLayout.ts 27.57 kB ($${\color{green}-90.1\%}$$)
tgpu_comptime.ts 15.18 kB ($${\color{green}-94.5\%}$$)
tgpu_unroll.ts 1.75 kB ($${\color{green}-99.4\%}$$)
tgpu_slot.ts 1.70 kB ($${\color{green}-99.4\%}$$)

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

Copilot AI 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.

Pull request overview

This PR adds GLSL-compatible handling for TypeGPU’s “implicit pointer” const-aliasing semantics, enabling the WebGL/GLSL fallback to preserve expected mutation behavior without native pointer support.

Changes:

  • Refactors WGSL const-alias handling into an overridable _aliasConstStatement hook.
  • Implements GLSL-specific aliasing rules: copy from immutable origins (e.g. uniforms), otherwise inline the aliased l-value expression and hoist runtime index expressions into temporaries to ensure single evaluation.
  • Adds a dedicated implicitPointer.test.ts suite covering immutable copies, mutable aliases, runtime index hoisting, and nested/alias-of-alias cases.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
packages/typegpu/src/tgsl/wgslGenerator.ts Extracts implicit-pointer const-alias logic into _aliasConstStatement for reuse/override.
packages/typegpu-gl/src/glslGenerator.ts Overrides const-alias lowering to be pointer-free in GLSL via copy-or-alias + index-hoisting.
packages/typegpu-gl/tests/implicitPointer.test.ts Adds snapshot tests validating GLSL output for implicit pointer scenarios.

💡 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.

Important

The substitution + index-hoisting design is sound and matches WGSL pointer semantics in the cases I traced, but the immutable branch copies aliased values via _emitVarDecl, which emits invalid GLSL ES 3.00 whenever the aliased value is array-typed (const a = u.arr;float a[4] = u.arr;, which GLSL ES 3.00 does not allow). See the inline comment for the fix.

Reviewed changes

  • GLSL alias const statements_aliasConstStatement override in glslGenerator.ts: copies aliases of immutable memory (uniform/readonly/handle) into locals, and turns mutable-memory aliases into compile-time substitutions of the aliased expression, hoisting non-constant index expressions into once-evaluated temp variables.
  • Index hoisting helper — new #hoistIndexAccesses walks member/index accesses and replaces runtime index expressions with @index_N references tied to freshly declared temps; comptime-constant indices are bound directly.
  • WGSL generator refactor — the implicit-pointer const handling in wgslGenerator.ts was extracted into a protected _aliasConstStatement hook with line-identical logic (makeUniqueIdentifier(rawId, 'block') preserved); WGSL generator/constant/struct tests still pass (139 tests).
  • New test suiteimplicitPointer.test.ts with six snapshot tests (immutable copy, mutable substitution, runtime-index hoisting, nested member/index chains, alias-of-an-alias, local-variable alias).

I verified the edge semantics directly: index expressions are snapshotted at the declaration (later reassignment of the index variable doesn't affect the alias, matching WGSL pointer-address semantics), and alias-of-alias chains resolve correctly through the stored expressions.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

Comment on lines +406 to +410
if (immutableOrigins.includes(eq.origin)) {
const dataType = undecorateDataType(eq.dataType as d.BaseData);
const name = this.ctx.makeUniqueIdentifier(rawId, 'block');
this.ctx.defineVariable(rawId, snip(name, dataType, 'runtime-immutable-def', false));
return this._emitVarDecl('let', name, dataType, this.ctx.resolveSnippet(eq).value);

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.

For array-typed immutable aliases this copies the array into a local, e.g. const a = uniformStruct.$.arr; (with arr a declared-uniform array field) generates float a[4] = uniformStruct.arr;. GLSL ES 3.00 does not allow initializing a variable from another array (only from array constructors), so this emits shader code that won't compile, while the equivalent code resolves fine in the WGSL generator (implicit pointer). I confirmed this exact output by resolving such a function against glOptions().

Since immutable sources can never change, substitution (treated exactly like the mutable branch — a rendered as uniformStruct.arr at every use) is semantically safe here and sidesteps the copy limitation entirely.

uniform Boid boid;

vec3 foo() {
vec3 boidPos = boid.pos;

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.

Consider a test covering a whole-array immutable alias (const a = uniform.arr; a[0]), which currently emits invalid GLSL as described in the comment on glslGenerator.ts:410, plus a runtime-indexed uniform element (uniform.arr[i]) to pin that the immutable copy path evaluates the index exactly once.

@iwoplaza
iwoplaza force-pushed the feat/glsl-implicit-pointer-definitions branch from 12cf3a1 to 1e1ea6e Compare August 10, 2026 10:06
@iwoplaza
iwoplaza force-pushed the feat/glsl-implicit-pointer-definitions branch from 1e1ea6e to 339c509 Compare August 10, 2026 10:17
@iwoplaza
iwoplaza force-pushed the feat/glsl-implicit-pointer-definitions branch from 339c509 to 8715ec1 Compare August 11, 2026 09:16
@iwoplaza
iwoplaza force-pushed the feat/glsl-implicit-pointer-definitions branch from 8715ec1 to abec4f8 Compare August 11, 2026 09:25
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.

feat(@typegpu/gl): Support implicit pointer definitions

2 participants