Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
e5068dd
Tracking referentiality
iwoplaza Sep 26, 2025
c5189be
More progress on the implementation
iwoplaza Sep 27, 2025
eb8f520
Mostly works now
iwoplaza Sep 27, 2025
5312d1d
Track ref address space
iwoplaza Sep 27, 2025
52124a7
Enforcing copy when assigning
iwoplaza Sep 27, 2025
07ed411
JS const with ref value is WGSL let with pointer
iwoplaza Sep 27, 2025
ba2a4ff
Fix ptr return types, and invalid ref and deref op order
iwoplaza Sep 27, 2025
7b7e5dc
Const statements
iwoplaza Sep 27, 2025
9a75b1e
Not allowing references to be returned from a function (unless it's a
iwoplaza Sep 27, 2025
5dc3884
Move member access exceptions to `accessProp` so that it's shared with
iwoplaza Sep 27, 2025
755d13b
Better indexing
iwoplaza Sep 27, 2025
ec2657f
Indexing arrays at comptime
iwoplaza Sep 27, 2025
8497a35
Constant tracking
iwoplaza Sep 27, 2025
cc349ff
Infix
iwoplaza Sep 27, 2025
77ac0cc
Apply formatting
iwoplaza Sep 27, 2025
04fa183
Merge branch 'main' into feat/ref-value
iwoplaza Oct 7, 2025
aee85a6
A few tweaks
iwoplaza Oct 7, 2025
5173502
Update wgslGenerator.ts
iwoplaza Oct 7, 2025
c3bf598
Fixes
iwoplaza Oct 7, 2025
40b3f7a
Self review
iwoplaza Oct 7, 2025
7c5900b
Update accessor.ts
iwoplaza Oct 7, 2025
50741ce
More tweaks
iwoplaza Oct 7, 2025
4dff99e
Merge branch 'main' into feat/ref-value
iwoplaza Oct 7, 2025
51c2919
Apply suggestion from @aleksanderkatan
iwoplaza Oct 8, 2025
b035d45
Apply suggestion from @aleksanderkatan
iwoplaza Oct 8, 2025
3932b2f
Update stable-fluid.test.ts
iwoplaza Oct 9, 2025
62936f8
Simplify 3D Fish compute
iwoplaza Oct 9, 2025
14c7282
Update compute.ts
iwoplaza Oct 9, 2025
e90832d
Review fixes
iwoplaza Oct 9, 2025
549bc71
Merge branch 'main' into feat/ref-value
iwoplaza Oct 10, 2025
e3b3bba
Merge branch 'main' into feat/ref-value
iwoplaza Oct 13, 2025
1e2df56
Updates after changing 'kernel' to 'use gpu'
iwoplaza Oct 13, 2025
bbc0508
feat: Better constant handling for ref/value tracking (#1801)
iwoplaza Oct 16, 2025
1f8392e
Merge branch 'main' into feat/ref-value
iwoplaza Oct 30, 2025
3824a3a
Update snapshots
iwoplaza Oct 30, 2025
b4f2c0b
Rename ref to origin
iwoplaza Oct 31, 2025
beb2295
Explicit refs
iwoplaza Nov 1, 2025
808deef
Merge branch 'main' into feat/ref-value
iwoplaza Nov 3, 2025
109dbe9
Implicit function pointers don't cause shell-less functions to generate
iwoplaza Nov 3, 2025
0fdadf5
Using std.neg when resolving unary `-` operator, and emitting `let` when
iwoplaza Nov 3, 2025
04fb153
Fix Disco example
iwoplaza Nov 3, 2025
2a6527e
🦕
iwoplaza Nov 3, 2025
59f2618
Updating gravity example
iwoplaza Nov 3, 2025
f85150b
More updates
iwoplaza Nov 3, 2025
05270d0
Update gravity.test.ts
iwoplaza Nov 3, 2025
66b89cf
Fixed!
iwoplaza Nov 3, 2025
2ed5955
Update Gravity code
iwoplaza Nov 3, 2025
4ccdd96
Working on umiform refs
iwoplaza Nov 4, 2025
dbcd394
Merge branch 'main' into feat/ref-value
iwoplaza Nov 4, 2025
07ee6b7
Writing internal docs about shader generation
iwoplaza Nov 4, 2025
79252cb
More useful refs
iwoplaza Nov 4, 2025
c853f5c
Simplify and document
iwoplaza Nov 4, 2025
21776b3
Test for updating a whole struct, returning refs
iwoplaza Nov 4, 2025
b1fe352
Updates
iwoplaza Nov 4, 2025
5805cac
Simplify implicit pointer dereferencing
iwoplaza Nov 5, 2025
37914d5
Merge branch 'main' into feat/ref-value
iwoplaza Nov 6, 2025
685479d
More tests and restrictions
iwoplaza Nov 6, 2025
171af79
More test coverage for argument origin tracking
iwoplaza Nov 6, 2025
c6b0537
Update shader-generation.mdx
iwoplaza Nov 6, 2025
b3e979e
Update shader-generation.mdx
iwoplaza Nov 6, 2025
e0b5cc7
🦕
iwoplaza Nov 6, 2025
39b5704
Merge branch 'main' into feat/ref-value
iwoplaza Nov 6, 2025
c31bb13
Better handling of arguments
iwoplaza Nov 6, 2025
6003bc3
Update pointers.ts
iwoplaza Nov 6, 2025
74d1291
Fix for referencing implicit pointers
iwoplaza Nov 7, 2025
5466542
feat: Inspect vector type in shader function
iwoplaza Nov 6, 2025
305f49e
Better
iwoplaza Nov 6, 2025
44c351b
Tweaks
iwoplaza Nov 6, 2025
0db2fb4
Merge branch 'main' into feat/comptime-vector-type-predicate
iwoplaza Dec 6, 2025
7f28896
Fixes
iwoplaza Dec 7, 2025
4375e8d
Update generationHelpers.ts
iwoplaza Dec 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Const statements
  • Loading branch information
iwoplaza committed Sep 27, 2025
commit 7b7e5dc7ede94884e652654f68202af5306cec65
8 changes: 2 additions & 6 deletions packages/typegpu/src/core/function/dualImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,12 @@ import {
type Snippet,
} from '../../data/snippet.ts';
import { inCodegenMode } from '../../execMode.ts';
import { type FnArgsConversionHint, getOwnSnippet } from '../../types.ts';
import { type FnArgsConversionHint, isKnownAtComptime } from '../../types.ts';
import { setName } from '../../shared/meta.ts';
import { $internal } from '../../shared/symbols.ts';
import { tryConvertSnippet } from '../../tgsl/conversion.ts';
import type { AnyData } from '../../data/dataTypes.ts';

function isKnownAtComptime(value: unknown): boolean {
return typeof value !== 'string' && getOwnSnippet(value) === undefined;
}

export function createDualImpl<T extends (...args: never[]) => unknown>(
jsImpl: T,
gpuImpl: (...args: MapValueToSnippet<Parameters<T>>) => Snippet,
Expand Down Expand Up @@ -81,7 +77,7 @@ export function dualImpl<T extends (...args: never[]) => unknown>(
}) as MapValueToSnippet<Parameters<T>>;

if (
!options.noComptime && converted.every((s) => isKnownAtComptime(s.value))
!options.noComptime && converted.every((s) => isKnownAtComptime(s))
) {
return snip(
options.normalImpl(...converted.map((s) => s.value) as never[]),
Expand Down
16 changes: 15 additions & 1 deletion packages/typegpu/src/tgsl/wgslGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ import { getName } from '../shared/meta.ts';
import { $internal } from '../shared/symbols.ts';
import { pow } from '../std/numeric.ts';
import { add, div, mul, sub } from '../std/operators.ts';
import { type FnArgsConversionHint, isMarkedInternal } from '../types.ts';
import {
type FnArgsConversionHint,
isKnownAtComptime,
isMarkedInternal,
} from '../types.ts';
import {
convertStructValues,
convertToCommonType,
Expand Down Expand Up @@ -818,6 +822,7 @@ ${this.ctx.pre}else ${alternate}`;
// Assigning a reference to a `const` variable means we store the pointer
// of the rhs.
if (eq.ref !== undefined) {
// Referential
if (stmtType === NODE.let) {
const rhsStr = this.ctx.resolve(eq.value).value;
const rhsTypeStr =
Expand All @@ -837,6 +842,15 @@ ${this.ctx.pre}else ${alternate}`;
if (!wgsl.isPtr(dataType)) {
dataType = ptrFn(concretize(dataType) as wgsl.StorableData);
}
} else {
// Non-referential
if (
stmtType === NODE.const &&
!wgsl.isNaturallyRef(dataType) &&
isKnownAtComptime(eq)
) {
varType = 'const';
}
}

const snippet = this.blockVariable(
Expand Down
5 changes: 5 additions & 0 deletions packages/typegpu/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,11 @@ export function getOwnSnippet(value: unknown): Snippet | undefined {
return (value as WithOwnSnippet)?.[$ownSnippet];
}

export function isKnownAtComptime(snippet: Snippet): boolean {
return typeof snippet.value !== 'string' &&
getOwnSnippet(snippet.value) === undefined;
}

export function isWgsl(value: unknown): value is Wgsl {
return (
typeof value === 'number' ||
Expand Down
4 changes: 2 additions & 2 deletions packages/typegpu/tests/accessor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ describe('tgpu.accessor', () => {
var color = vec3f(1, 0, 0);
let color2 = (&redUniform);
var color3 = getColor();
var colorX = 1;
const colorX = 1;
var color2X = redUniform.x;
var color3X = getColor().x;
}"
Expand All @@ -180,7 +180,7 @@ describe('tgpu.accessor', () => {

expect(asWgsl(main)).toMatchInlineSnapshot(`
"fn main() {
var foo = 1f;
const foo = 1f;
}"
`);
});
Expand Down
2 changes: 1 addition & 1 deletion packages/typegpu/tests/derived.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ describe('TgpuDerived', () => {

fn func() {
var pos = vec3f(2, 4, 6);
var posX = 2;
const posX = 2;
let vel = (&boid.vel);
var velX = boid.vel.x;
let vel_ = (&boid.vel);
Expand Down
8 changes: 4 additions & 4 deletions packages/typegpu/tests/examples/individual/3d-fish.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ describe('3d fish example', () => {
repulsion[i] = 1;
var axisAquariumSize = (vec3f(10, 4, 10)[i] / 2f);
var axisPosition = fishData.position[i];
var distance = 0.1;
const distance = 0.1;
if ((axisPosition > (axisAquariumSize - distance))) {
var str = (axisPosition - (axisAquariumSize - distance));
wallRepulsion = (wallRepulsion - (str * repulsion));
Expand All @@ -184,7 +184,7 @@ describe('3d fish example', () => {
if ((mouseRay_5.activated == 1)) {
var proj = projectPointOnLine_8((&fishData.position), (&mouseRay_5.line));
var diff = (fishData.position - proj);
var limit = 0.9;
const limit = 0.9;
var str = (pow(2, clamp((limit - length(diff)), 0, limit)) - 1);
rayRepulsion = (str * normalize(diff));
}
Expand Down Expand Up @@ -218,8 +218,8 @@ describe('3d fish example', () => {

fn applySinWave_4(index: u32, vertex: PosAndNormal_3, time: f32) -> PosAndNormal_3 {
var a = -60.1;
var b = 0.8;
var c = 6.1;
const b = 0.8;
const c = 6.1;
var posMod = vec3f();
posMod.z = (sin((f32(index) + (((time / a) + vertex.position.x) / b))) / c);
var coeff = (cos((f32(index) + (((time / a) + vertex.position.x) / b))) / c);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ describe('box raytracing example', () => {
}
var linear = (vec3f(1) / invColor);
var srgb = linearToSrgb_12(linear);
var gamma = 2.2;
const gamma = 2.2;
var corrected = pow(srgb, vec3f((1f / gamma)));
if (intersectionFound) {
return (min(density, 1) * vec4f(min(corrected, vec3f(1)), 1));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ describe('fluid double buffering example', () => {
}

fn computeVelocity_8(x: i32, y: i32) -> vec2f {
var gravityCost = 0.5;
const gravityCost = 0.5;
var neighborOffsets = array<vec2i, 4>(vec2i(0, 1), vec2i(0, -1), vec2i(1, 0), vec2i(-1, 0));
var cell = getCell_6(x, y);
var leastCost = cell.z;
Expand Down Expand Up @@ -216,7 +216,7 @@ describe('fluid double buffering example', () => {
@group(0) @binding(3) var<uniform> sourceParams_18: item_19;

fn getMinimumInFlow_17(x: i32, y: i32) -> f32 {
var gridSizeF = 256f;
const gridSizeF = 256f;
var sourceRadius2 = max(1, (sourceParams_18.radius * gridSizeF));
var sourcePos = vec2f((sourceParams_18.center.x * gridSizeF), (sourceParams_18.center.y * gridSizeF));
if ((distance(vec2f(f32(x), f32(y)), sourcePos) < sourceRadius2)) {
Expand Down Expand Up @@ -324,7 +324,7 @@ describe('fluid double buffering example', () => {
}

fn computeVelocity_8(x: i32, y: i32) -> vec2f {
var gravityCost = 0.5;
const gravityCost = 0.5;
var neighborOffsets = array<vec2i, 4>(vec2i(0, 1), vec2i(0, -1), vec2i(1, 0), vec2i(-1, 0));
var cell = getCell_6(x, y);
var leastCost = cell.z;
Expand Down Expand Up @@ -383,7 +383,7 @@ describe('fluid double buffering example', () => {
@group(0) @binding(3) var<uniform> sourceParams_18: item_19;

fn getMinimumInFlow_17(x: i32, y: i32) -> f32 {
var gridSizeF = 256f;
const gridSizeF = 256f;
var sourceRadius2 = max(1, (sourceParams_18.radius * gridSizeF));
var sourcePos = vec2f((sourceParams_18.center.x * gridSizeF), (sourceParams_18.center.y * gridSizeF));
if ((distance(vec2f(f32(x), f32(y)), sourcePos) < sourceRadius2)) {
Expand Down Expand Up @@ -478,9 +478,9 @@ describe('fluid double buffering example', () => {
var firstColor = vec4f(0.20000000298023224, 0.6000000238418579, 1, 1);
var secondColor = vec4f(0.20000000298023224, 0.30000001192092896, 0.6000000238418579, 1);
var thirdColor = vec4f(0.10000000149011612, 0.20000000298023224, 0.4000000059604645, 1);
var firstThreshold = 2f;
var secondThreshold = 10f;
var thirdThreshold = 20f;
const firstThreshold = 2f;
const secondThreshold = 10f;
const thirdThreshold = 20f;
if (isInsideObstacle_6(x, y)) {
return obstacleColor;
}
Expand Down
6 changes: 3 additions & 3 deletions packages/typegpu/tests/examples/individual/oklab.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ describe('oklab example', () => {
}

fn findGamutIntersection_13(a: f32, b: f32, L1: f32, C1: f32, L0: f32, cusp: LC_12) -> f32 {
var FLT_MAX = 3.4028234663852886e+38f;
const FLT_MAX = 3.4028234663852886e+38f;
var t = 0f;
if (((((L1 - L0) * cusp.C) - ((cusp.L - L0) * C1)) <= 0)) {
t = ((cusp.C * L0) / ((C1 * cusp.L) + (cusp.C * (L0 - L1))));
Expand Down Expand Up @@ -193,9 +193,9 @@ describe('oklab example', () => {
}

fn gamutClipAdaptiveL05_8(lab: vec3f) -> vec3f {
var alpha = 0.20000000298023224f;
const alpha = 0.20000000298023224f;
var L = lab.x;
var eps = 1e-5;
const eps = 1e-5;
var C = max(eps, length(lab.yz));
var a_ = (lab.y / C);
var b_ = (lab.z / C);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,15 @@ describe('ray-marching example', () => {

fn getNormal_16(p: ptr<function, vec3f>) -> vec3f {
var dist = getSceneDist_7(p).dist;
var e = 0.01;
const e = 0.01;
var n = vec3f((getSceneDist_17(((*p) + vec3f(e, 0, 0))).dist - dist), (getSceneDist_17(((*p) + vec3f(0, e, 0))).dist - dist), (getSceneDist_17(((*p) + vec3f(0, 0, e))).dist - dist));
return normalize(n);
}

fn getOrbitingLightPos_19(t: f32) -> vec3f {
var radius = 3f;
var height = 6f;
var speed = 1f;
const radius = 3f;
const height = 6f;
const speed = 1f;
return vec3f((cos((t * speed)) * radius), (height + (sin((t * speed)) * radius)), 4);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,14 +240,14 @@ describe('stable-fluid example', () => {
}

@fragment fn fragmentImageFn_3(input: fragmentImageFn_Input_7) -> @location(0) vec4f {
var pixelStep = 0.001953125f;
const pixelStep = 0.001953125f;
var leftSample = textureSample(result_4, linSampler_5, vec2f((input.uv.x - pixelStep), input.uv.y)).x;
var rightSample = textureSample(result_4, linSampler_5, vec2f((input.uv.x + pixelStep), input.uv.y)).x;
var upSample = textureSample(result_4, linSampler_5, vec2f(input.uv.x, (input.uv.y + pixelStep))).x;
var downSample = textureSample(result_4, linSampler_5, vec2f(input.uv.x, (input.uv.y - pixelStep))).x;
var gradientX = (rightSample - leftSample);
var gradientY = (upSample - downSample);
var distortStrength = 0.8;
const distortStrength = 0.8;
var distortVector = vec2f(gradientX, gradientY);
var distortedUV = (input.uv + (distortVector * vec2f(distortStrength, -distortStrength)));
var outputColor = textureSample(background_6, linSampler_5, vec2f(distortedUV.x, (1 - distortedUV.y)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ describe('tgsl parsing test example', () => {

fn pointersTest_11() -> bool {
var s = true;
var num = 0u;
const num = 0u;
modifyNumFn_12((&num));
s = (s && (num == 1));
var vec = vec2f();
Expand Down
10 changes: 5 additions & 5 deletions packages/typegpu/tests/numeric.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ describe('TGSL', () => {

expect(asWgsl(main)).toMatchInlineSnapshot(`
"fn main() {
var f = 0f;
var h = 0h;
var i = 0i;
var u = 0u;
var b = false;
const f = 0f;
const h = 0h;
const i = 0i;
const u = 0u;
const b = false;
}"
`);
});
Expand Down
2 changes: 1 addition & 1 deletion packages/typegpu/tests/slot.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ describe('tgpu.slot', () => {

fn func() {
var pos = vec3f(1, 2, 3);
var posX = 1;
const posX = 1;
let vel = (&boid.vel);
var velX = boid.vel.x;
let vel_ = (&boid.vel);
Expand Down
36 changes: 13 additions & 23 deletions packages/typegpu/tests/std/matrix/rotate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('rotate', () => {

expect(asWgsl(rotateFn)).toMatchInlineSnapshot(`
"fn rotateFn() {
var angle = 4;
const angle = 4;
var resultExpression = (mat4x4f(1, 0, 0, 0, 0, cos(angle), sin(angle), 0, 0, -sin(angle), cos(angle), 0, 0, 0, 0, 1) * mat4x4f(1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1));
}"
`);
Expand All @@ -30,17 +30,12 @@ describe('rotate', () => {
const resultExpression = rotateY4(M, angle);
});

expect(parseResolved({ rotateFn })).toBe(
parse(
`fn rotateFn() {
var angle = 4;
var resultExpression = (
mat4x4f(cos(angle), 0, -sin(angle), 0, 0, 1, 0, 0, sin(angle), 0, cos(angle), 0, 0, 0, 0, 1) *
mat4x4f(1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1)
);
}`,
),
);
expect(asWgsl(rotateFn)).toMatchInlineSnapshot(`
"fn rotateFn() {
const angle = 4;
var resultExpression = (mat4x4f(cos(angle), 0, -sin(angle), 0, 0, 1, 0, 0, sin(angle), 0, cos(angle), 0, 0, 0, 0, 1) * mat4x4f(1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1));
}"
`);
});

it('generates correct WGSL for rotateZ4 with custom matrix', () => {
Expand All @@ -51,17 +46,12 @@ describe('rotate', () => {
const resultExpression = rotateZ4(M, angle);
});

expect(parseResolved({ rotateFn })).toBe(
parse(
`fn rotateFn() {
var angle = 4;
var resultExpression = (
mat4x4f(cos(angle), sin(angle), 0, 0, -sin(angle), cos(angle), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) *
mat4x4f(1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1)
);
}`,
),
);
expect(asWgsl(rotateFn)).toMatchInlineSnapshot(`
"fn rotateFn() {
const angle = 4;
var resultExpression = (mat4x4f(cos(angle), sin(angle), 0, 0, -sin(angle), cos(angle), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) * mat4x4f(1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1));
}"
`);
});

it('rotates around X correctly', () => {
Expand Down
Loading