From fc9bb1278035bef468dfcea7e55c284c488ce08e Mon Sep 17 00:00:00 2001 From: Aleksander Katan Date: Wed, 7 Jan 2026 15:16:55 +0100 Subject: [PATCH 01/11] Add an autoname test --- .../typegpu/tests/unplugin/autoname.test.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/packages/typegpu/tests/unplugin/autoname.test.ts b/packages/typegpu/tests/unplugin/autoname.test.ts index 92b4641049..8fc38565f8 100644 --- a/packages/typegpu/tests/unplugin/autoname.test.ts +++ b/packages/typegpu/tests/unplugin/autoname.test.ts @@ -235,4 +235,22 @@ describe('autonaming', () => { expect(getName(myController.myBuffer)).toBe('myBuffer'); }); + + it('autonames this private prop assignment', ({ root }) => { + class MyController { + #myBuffer; + + constructor() { + this.#myBuffer = root.createUniform(d.u32); + } + + get myBuffer() { + return this.#myBuffer; + } + } + + const myController = new MyController(); + + expect(getName(myController.myBuffer)).toBe('myBuffer'); + }); }); From 28734e10f34f95e7212d6885fc3ee138a3b5ef76 Mon Sep 17 00:00:00 2001 From: Aleksander Katan Date: Wed, 7 Jan 2026 15:38:23 +0100 Subject: [PATCH 02/11] More tests --- .../unplugin-typegpu/test/auto-naming.test.ts | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/packages/unplugin-typegpu/test/auto-naming.test.ts b/packages/unplugin-typegpu/test/auto-naming.test.ts index cc76ce5a7c..53f13fec45 100644 --- a/packages/unplugin-typegpu/test/auto-naming.test.ts +++ b/packages/unplugin-typegpu/test/auto-naming.test.ts @@ -429,6 +429,46 @@ describe('[BABEL] auto naming', () => { }" `); }); + + it('works with assigning to "this" property', () => { + const code = `\ + import tgpu from 'typegpu'; + import * as d from 'typegpu/data'; + + const root = await tgpu.init(); + + class MyController { + #myBuffer; + + constructor() { + this.#myBuffer = root.createUniform(d.u32); + } + + get myBuffer() { + return this.#myBuffer; + } + } + + console.log(MyController); + `; + + expect(babelTransform(code, { autoNamingEnabled: true })) + .toMatchInlineSnapshot(` + "import tgpu from 'typegpu'; + import * as d from 'typegpu/data'; + const root = await tgpu.init(); + class MyController { + #myBuffer; + constructor() { + this.#myBuffer = root.createUniform(d.u32); + } + get myBuffer() { + return this.#myBuffer; + } + } + console.log(MyController);" + `); + }); }); describe('[ROLLUP] auto naming', () => { @@ -875,4 +915,50 @@ describe('[ROLLUP] auto naming', () => { " `); }); + + it('works with assigning to "this" property', async () => { + const code = `\ + import tgpu from 'typegpu'; + import * as d from 'typegpu/data'; + + const root = await tgpu.init(); + + class MyController { + #myBuffer; + + constructor() { + this.#myBuffer = root.createUniform(d.u32); + } + + get myBuffer() { + return this.#myBuffer; + } + } + + console.log(MyController); + `; + + expect(await rollupTransform(code, { autoNamingEnabled: true })) + .toMatchInlineSnapshot(` + "import tgpu from 'typegpu'; + import * as d from 'typegpu/data'; + + const root = await tgpu.init(); + + class MyController { + #myBuffer; + + constructor() { + this.#myBuffer = root.createUniform(d.u32); + } + + get myBuffer() { + return this.#myBuffer; + } + } + + console.log(MyController); + " + `); + }); }); From 56f6a05f4d43a8d879f74a85bab985282be5f525 Mon Sep 17 00:00:00 2001 From: Aleksander Katan Date: Wed, 7 Jan 2026 15:59:22 +0100 Subject: [PATCH 03/11] Update autonaming --- packages/unplugin-typegpu/src/common.ts | 6 ++++++ packages/unplugin-typegpu/test/auto-naming.test.ts | 8 ++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/unplugin-typegpu/src/common.ts b/packages/unplugin-typegpu/src/common.ts index b6395e4b4b..91ccbd9b2a 100644 --- a/packages/unplugin-typegpu/src/common.ts +++ b/packages/unplugin-typegpu/src/common.ts @@ -226,6 +226,12 @@ function tryFindIdentifier( if (node.type === 'Identifier') { return node.name; } + if (node.type === 'PrivateName') { + return tryFindIdentifier(node.id); + } + if (node.type === 'PrivateIdentifier') { + return node.name; + } if (node.type === 'MemberExpression') { return tryFindIdentifier(node.property); } diff --git a/packages/unplugin-typegpu/test/auto-naming.test.ts b/packages/unplugin-typegpu/test/auto-naming.test.ts index 53f13fec45..50441f5440 100644 --- a/packages/unplugin-typegpu/test/auto-naming.test.ts +++ b/packages/unplugin-typegpu/test/auto-naming.test.ts @@ -430,7 +430,7 @@ describe('[BABEL] auto naming', () => { `); }); - it('works with assigning to "this" property', () => { + it('works with assigning to "this" private property', () => { const code = `\ import tgpu from 'typegpu'; import * as d from 'typegpu/data'; @@ -460,7 +460,7 @@ describe('[BABEL] auto naming', () => { class MyController { #myBuffer; constructor() { - this.#myBuffer = root.createUniform(d.u32); + this.#myBuffer = (globalThis.__TYPEGPU_AUTONAME__ ?? (a => a))(root.createUniform(d.u32), "myBuffer"); } get myBuffer() { return this.#myBuffer; @@ -916,7 +916,7 @@ describe('[ROLLUP] auto naming', () => { `); }); - it('works with assigning to "this" property', async () => { + it('works with assigning to "this" private property', async () => { const code = `\ import tgpu from 'typegpu'; import * as d from 'typegpu/data'; @@ -949,7 +949,7 @@ describe('[ROLLUP] auto naming', () => { #myBuffer; constructor() { - this.#myBuffer = root.createUniform(d.u32); + this.#myBuffer = ((globalThis.__TYPEGPU_AUTONAME__ ?? (a => a))(root.createUniform(d.u32), "myBuffer")); } get myBuffer() { From b3230dc3ae2d8888fa5f6bd772dde6a06f1b6d08 Mon Sep 17 00:00:00 2001 From: Aleksander Katan Date: Wed, 7 Jan 2026 16:51:07 +0100 Subject: [PATCH 04/11] Update tests --- packages/typegpu/src/nameRegistry.ts | 2 + .../examples/individual/jelly-slider.test.ts | 6 +- .../examples/individual/jelly-switch.test.ts | 6 +- .../examples/individual/probability.test.ts | 118 +++++++++--------- 4 files changed, 67 insertions(+), 65 deletions(-) diff --git a/packages/typegpu/src/nameRegistry.ts b/packages/typegpu/src/nameRegistry.ts index 82c7650c81..b97a9b30c6 100644 --- a/packages/typegpu/src/nameRegistry.ts +++ b/packages/typegpu/src/nameRegistry.ts @@ -175,6 +175,8 @@ const bannedTokens = new Set([ 'yield', // Keywords that should be reserved 'sampler', + // 'uniform', + // 'storage', ]); const builtins = new Set([ diff --git a/packages/typegpu/tests/examples/individual/jelly-slider.test.ts b/packages/typegpu/tests/examples/individual/jelly-slider.test.ts index 2a0c3f152a..7e96fbdd57 100644 --- a/packages/typegpu/tests/examples/individual/jelly-slider.test.ts +++ b/packages/typegpu/tests/examples/individual/jelly-slider.test.ts @@ -86,7 +86,7 @@ describe('jelly-slider example', () => { projInv: mat4x4f, } - @group(0) @binding(1) var cameraUniform: Camera; + @group(0) @binding(1) var uniform: Camera; struct Ray { origin: vec3f, @@ -95,8 +95,8 @@ describe('jelly-slider example', () => { fn getRay(ndc: vec2f) -> Ray { var clipPos = vec4f(ndc.x, ndc.y, -1f, 1f); - let invView = (&cameraUniform.viewInv); - let invProj = (&cameraUniform.projInv); + let invView = (&uniform.viewInv); + let invProj = (&uniform.projInv); var viewPos = ((*invProj) * clipPos); var viewPosNormalized = vec4f((viewPos.xyz / viewPos.w), 1f); var worldPos = ((*invView) * viewPosNormalized); diff --git a/packages/typegpu/tests/examples/individual/jelly-switch.test.ts b/packages/typegpu/tests/examples/individual/jelly-switch.test.ts index 5ab301f504..3ded3a5275 100644 --- a/packages/typegpu/tests/examples/individual/jelly-switch.test.ts +++ b/packages/typegpu/tests/examples/individual/jelly-switch.test.ts @@ -60,7 +60,7 @@ describe('jelly switch example', () => { projInv: mat4x4f, } - @group(0) @binding(1) var cameraUniform: Camera; + @group(0) @binding(1) var uniform: Camera; struct Ray { origin: vec3f, @@ -69,8 +69,8 @@ describe('jelly switch example', () => { fn getRay(ndc: vec2f) -> Ray { var clipPos = vec4f(ndc.x, ndc.y, -1f, 1f); - let invView = (&cameraUniform.viewInv); - let invProj = (&cameraUniform.projInv); + let invView = (&uniform.viewInv); + let invProj = (&uniform.projInv); var viewPos = ((*invProj) * clipPos); var viewPosNormalized = vec4f((viewPos.xyz / viewPos.w), 1f); var worldPos = ((*invView) * viewPosNormalized); diff --git a/packages/typegpu/tests/examples/individual/probability.test.ts b/packages/typegpu/tests/examples/individual/probability.test.ts index 62276f55f7..0c0843ae3b 100644 --- a/packages/typegpu/tests/examples/individual/probability.test.ts +++ b/packages/typegpu/tests/examples/individual/probability.test.ts @@ -32,7 +32,7 @@ describe('probability distribution plot example', () => { seed_1(seed); } - fn item_1() -> f32 { + fn item() -> f32 { let a = dot(seed, vec2f(23.140779495239258, 232.6168975830078)); let b = dot(seed, vec2f(54.47856521606445, 345.8415222167969)); seed.x = fract((cos(a) * 136.8168f)); @@ -41,7 +41,7 @@ describe('probability distribution plot example', () => { } fn randUniformExclusive() -> f32 { - return ((item_1() * 0.9999998f) + 1e-7f); + return ((item() * 0.9999998f) + 1e-7f); } fn randNormal(mu: f32, sigma: f32) -> f32 { @@ -51,17 +51,17 @@ describe('probability distribution plot example', () => { } fn randInUnitSphere() -> vec3f { - let u = item_1(); + let u = item(); var v = vec3f(randNormal(0f, 1f), randNormal(0f, 1f), randNormal(0f, 1f)); var vNorm = normalize(v); return (vNorm * pow(u, 0.33f)); } - struct item_2 { + struct dataMoreWorkersFunc_Input { @builtin(global_invocation_id) gid: vec3u, } - @compute @workgroup_size(64) fn item(input: item_2) { + @compute @workgroup_size(64) fn dataMoreWorkersFunc(input: dataMoreWorkersFunc_Input) { let id = input.gid.x; if ((id >= arrayLength(&samplesBuffer))) { return; @@ -84,7 +84,7 @@ describe('probability distribution plot example', () => { seed_1(seed); } - fn item_1() -> f32 { + fn item() -> f32 { let a = dot(seed, vec2f(23.140779495239258, 232.6168975830078)); let b = dot(seed, vec2f(54.47856521606445, 345.8415222167969)); seed.x = fract((cos(a) * 136.8168f)); @@ -93,19 +93,19 @@ describe('probability distribution plot example', () => { } fn randOnUnitSphere() -> vec3f { - let z = ((2f * item_1()) - 1f); + let z = ((2f * item()) - 1f); let oneMinusZSq = sqrt((1f - (z * z))); - let theta = (6.283185307179586f * item_1()); + let theta = (6.283185307179586f * item()); let x = (cos(theta) * oneMinusZSq); let y = (sin(theta) * oneMinusZSq); return vec3f(x, y, z); } - struct item_2 { + struct dataMoreWorkersFunc_Input { @builtin(global_invocation_id) gid: vec3u, } - @compute @workgroup_size(64) fn item(input: item_2) { + @compute @workgroup_size(64) fn dataMoreWorkersFunc(input: dataMoreWorkersFunc_Input) { let id = input.gid.x; if ((id >= arrayLength(&samplesBuffer))) { return; @@ -128,7 +128,7 @@ describe('probability distribution plot example', () => { seed_1(seed); } - fn item_1() -> f32 { + fn item() -> f32 { let a = dot(seed, vec2f(23.140779495239258, 232.6168975830078)); let b = dot(seed, vec2f(54.47856521606445, 345.8415222167969)); seed.x = fract((cos(a) * 136.8168f)); @@ -137,8 +137,8 @@ describe('probability distribution plot example', () => { } fn randInUnitCircle() -> vec2f { - let radius = sqrt(item_1()); - let angle = (item_1() * 6.283185307179586f); + let radius = sqrt(item()); + let angle = (item() * 6.283185307179586f); return vec2f((cos(angle) * radius), (sin(angle) * radius)); } @@ -146,11 +146,11 @@ describe('probability distribution plot example', () => { return vec3f(randInUnitCircle(), 0.5f); } - struct item_2 { + struct dataMoreWorkersFunc_Input { @builtin(global_invocation_id) gid: vec3u, } - @compute @workgroup_size(64) fn item(input: item_2) { + @compute @workgroup_size(64) fn dataMoreWorkersFunc(input: dataMoreWorkersFunc_Input) { let id = input.gid.x; if ((id >= arrayLength(&samplesBuffer))) { return; @@ -173,7 +173,7 @@ describe('probability distribution plot example', () => { seed_1(seed); } - fn item_1() -> f32 { + fn item() -> f32 { let a = dot(seed, vec2f(23.140779495239258, 232.6168975830078)); let b = dot(seed, vec2f(54.47856521606445, 345.8415222167969)); seed.x = fract((cos(a) * 136.8168f)); @@ -182,7 +182,7 @@ describe('probability distribution plot example', () => { } fn randOnUnitCircle() -> vec2f { - let angle = (item_1() * 6.283185307179586f); + let angle = (item() * 6.283185307179586f); return vec2f(cos(angle), sin(angle)); } @@ -190,11 +190,11 @@ describe('probability distribution plot example', () => { return vec3f(randOnUnitCircle(), 0.5f); } - struct item_2 { + struct dataMoreWorkersFunc_Input { @builtin(global_invocation_id) gid: vec3u, } - @compute @workgroup_size(64) fn item(input: item_2) { + @compute @workgroup_size(64) fn dataMoreWorkersFunc(input: dataMoreWorkersFunc_Input) { let id = input.gid.x; if ((id >= arrayLength(&samplesBuffer))) { return; @@ -217,7 +217,7 @@ describe('probability distribution plot example', () => { seed_1(seed); } - fn item_1() -> f32 { + fn item() -> f32 { let a = dot(seed, vec2f(23.140779495239258, 232.6168975830078)); let b = dot(seed, vec2f(54.47856521606445, 345.8415222167969)); seed.x = fract((cos(a) * 136.8168f)); @@ -226,14 +226,14 @@ describe('probability distribution plot example', () => { } fn randInUnitCube() -> vec3f { - return vec3f(item_1(), item_1(), item_1()); + return vec3f(item(), item(), item()); } - struct item_2 { + struct dataMoreWorkersFunc_Input { @builtin(global_invocation_id) gid: vec3u, } - @compute @workgroup_size(64) fn item(input: item_2) { + @compute @workgroup_size(64) fn dataMoreWorkersFunc(input: dataMoreWorkersFunc_Input) { let id = input.gid.x; if ((id >= arrayLength(&samplesBuffer))) { return; @@ -256,7 +256,7 @@ describe('probability distribution plot example', () => { seed_1(seed); } - fn item_1() -> f32 { + fn item() -> f32 { let a = dot(seed, vec2f(23.140779495239258, 232.6168975830078)); let b = dot(seed, vec2f(54.47856521606445, 345.8415222167969)); seed.x = fract((cos(a) * 136.8168f)); @@ -265,20 +265,20 @@ describe('probability distribution plot example', () => { } fn randOnUnitCube() -> vec3f { - let face = u32((item_1() * 6f)); + let face = u32((item() * 6f)); let axis = (face % 3u); var result = vec3f(); result[axis] = f32(select(0, 1, (face > 2u))); - result[((axis + 1u) % 3u)] = item_1(); - result[((axis + 2u) % 3u)] = item_1(); + result[((axis + 1u) % 3u)] = item(); + result[((axis + 2u) % 3u)] = item(); return result; } - struct item_2 { + struct dataMoreWorkersFunc_Input { @builtin(global_invocation_id) gid: vec3u, } - @compute @workgroup_size(64) fn item(input: item_2) { + @compute @workgroup_size(64) fn dataMoreWorkersFunc(input: dataMoreWorkersFunc_Input) { let id = input.gid.x; if ((id >= arrayLength(&samplesBuffer))) { return; @@ -301,7 +301,7 @@ describe('probability distribution plot example', () => { seed_1(seed); } - fn item_1() -> f32 { + fn item() -> f32 { let a = dot(seed, vec2f(23.140779495239258, 232.6168975830078)); let b = dot(seed, vec2f(54.47856521606445, 345.8415222167969)); seed.x = fract((cos(a) * 136.8168f)); @@ -310,7 +310,7 @@ describe('probability distribution plot example', () => { } fn randUniformExclusive() -> f32 { - return ((item_1() * 0.9999998f) + 1e-7f); + return ((item() * 0.9999998f) + 1e-7f); } fn randNormal(mu: f32, sigma: f32) -> f32 { @@ -320,7 +320,7 @@ describe('probability distribution plot example', () => { } fn randInUnitSphere() -> vec3f { - let u = item_1(); + let u = item(); var v = vec3f(randNormal(0f, 1f), randNormal(0f, 1f), randNormal(0f, 1f)); var vNorm = normalize(v); return (vNorm * pow(u, 0.33f)); @@ -336,11 +336,11 @@ describe('probability distribution plot example', () => { return randInUnitHemisphere(vec3f(1.409999966621399, 1.409999966621399, 0)); } - struct item_2 { + struct dataMoreWorkersFunc_Input { @builtin(global_invocation_id) gid: vec3u, } - @compute @workgroup_size(64) fn item(input: item_2) { + @compute @workgroup_size(64) fn dataMoreWorkersFunc(input: dataMoreWorkersFunc_Input) { let id = input.gid.x; if ((id >= arrayLength(&samplesBuffer))) { return; @@ -363,7 +363,7 @@ describe('probability distribution plot example', () => { seed_1(seed); } - fn item_1() -> f32 { + fn item() -> f32 { let a = dot(seed, vec2f(23.140779495239258, 232.6168975830078)); let b = dot(seed, vec2f(54.47856521606445, 345.8415222167969)); seed.x = fract((cos(a) * 136.8168f)); @@ -372,9 +372,9 @@ describe('probability distribution plot example', () => { } fn randOnUnitSphere() -> vec3f { - let z = ((2f * item_1()) - 1f); + let z = ((2f * item()) - 1f); let oneMinusZSq = sqrt((1f - (z * z))); - let theta = (6.283185307179586f * item_1()); + let theta = (6.283185307179586f * item()); let x = (cos(theta) * oneMinusZSq); let y = (sin(theta) * oneMinusZSq); return vec3f(x, y, z); @@ -390,11 +390,11 @@ describe('probability distribution plot example', () => { return randOnUnitHemisphere(vec3f(1.409999966621399, 1.409999966621399, 0)); } - struct item_2 { + struct dataMoreWorkersFunc_Input { @builtin(global_invocation_id) gid: vec3u, } - @compute @workgroup_size(64) fn item(input: item_2) { + @compute @workgroup_size(64) fn dataMoreWorkersFunc(input: dataMoreWorkersFunc_Input) { let id = input.gid.x; if ((id >= arrayLength(&samplesBuffer))) { return; @@ -417,7 +417,7 @@ describe('probability distribution plot example', () => { seed_1(seed); } - fn item_1() -> f32 { + fn item() -> f32 { let a = dot(seed, vec2f(23.140779495239258, 232.6168975830078)); let b = dot(seed, vec2f(54.47856521606445, 345.8415222167969)); seed.x = fract((cos(a) * 136.8168f)); @@ -426,7 +426,7 @@ describe('probability distribution plot example', () => { } fn randBernoulli(p: f32) -> f32 { - let u = item_1(); + let u = item(); return step(u, p); } @@ -434,11 +434,11 @@ describe('probability distribution plot example', () => { return vec3f(randBernoulli(0.7f)); } - struct item_2 { + struct dataMoreWorkersFunc_Input { @builtin(global_invocation_id) gid: vec3u, } - @compute @workgroup_size(64) fn item(input: item_2) { + @compute @workgroup_size(64) fn dataMoreWorkersFunc(input: dataMoreWorkersFunc_Input) { let id = input.gid.x; if ((id >= arrayLength(&samplesBuffer))) { return; @@ -461,7 +461,7 @@ describe('probability distribution plot example', () => { seed_1(seed); } - fn item_1() -> f32 { + fn item() -> f32 { let a = dot(seed, vec2f(23.140779495239258, 232.6168975830078)); let b = dot(seed, vec2f(54.47856521606445, 345.8415222167969)); seed.x = fract((cos(a) * 136.8168f)); @@ -470,18 +470,18 @@ describe('probability distribution plot example', () => { } fn randFloat01() -> f32 { - return item_1(); + return item(); } fn prng() -> vec3f { return vec3f(randFloat01()); } - struct item_2 { + struct dataMoreWorkersFunc_Input { @builtin(global_invocation_id) gid: vec3u, } - @compute @workgroup_size(64) fn item(input: item_2) { + @compute @workgroup_size(64) fn dataMoreWorkersFunc(input: dataMoreWorkersFunc_Input) { let id = input.gid.x; if ((id >= arrayLength(&samplesBuffer))) { return; @@ -504,7 +504,7 @@ describe('probability distribution plot example', () => { seed_1(seed); } - fn item_1() -> f32 { + fn item() -> f32 { let a = dot(seed, vec2f(23.140779495239258, 232.6168975830078)); let b = dot(seed, vec2f(54.47856521606445, 345.8415222167969)); seed.x = fract((cos(a) * 136.8168f)); @@ -513,7 +513,7 @@ describe('probability distribution plot example', () => { } fn randUniformExclusive() -> f32 { - return ((item_1() * 0.9999998f) + 1e-7f); + return ((item() * 0.9999998f) + 1e-7f); } fn randExponential(rate: f32) -> f32 { @@ -525,11 +525,11 @@ describe('probability distribution plot example', () => { return vec3f(randExponential(1f)); } - struct item_2 { + struct dataMoreWorkersFunc_Input { @builtin(global_invocation_id) gid: vec3u, } - @compute @workgroup_size(64) fn item(input: item_2) { + @compute @workgroup_size(64) fn dataMoreWorkersFunc(input: dataMoreWorkersFunc_Input) { let id = input.gid.x; if ((id >= arrayLength(&samplesBuffer))) { return; @@ -552,7 +552,7 @@ describe('probability distribution plot example', () => { seed_1(seed); } - fn item_1() -> f32 { + fn item() -> f32 { let a = dot(seed, vec2f(23.140779495239258, 232.6168975830078)); let b = dot(seed, vec2f(54.47856521606445, 345.8415222167969)); seed.x = fract((cos(a) * 136.8168f)); @@ -561,7 +561,7 @@ describe('probability distribution plot example', () => { } fn randUniformExclusive() -> f32 { - return ((item_1() * 0.9999998f) + 1e-7f); + return ((item() * 0.9999998f) + 1e-7f); } fn randNormal(mu: f32, sigma: f32) -> f32 { @@ -574,11 +574,11 @@ describe('probability distribution plot example', () => { return vec3f(randNormal(0f, 1f)); } - struct item_2 { + struct dataMoreWorkersFunc_Input { @builtin(global_invocation_id) gid: vec3u, } - @compute @workgroup_size(64) fn item(input: item_2) { + @compute @workgroup_size(64) fn dataMoreWorkersFunc(input: dataMoreWorkersFunc_Input) { let id = input.gid.x; if ((id >= arrayLength(&samplesBuffer))) { return; @@ -601,7 +601,7 @@ describe('probability distribution plot example', () => { seed_1(seed); } - fn item_1() -> f32 { + fn item() -> f32 { let a = dot(seed, vec2f(23.140779495239258, 232.6168975830078)); let b = dot(seed, vec2f(54.47856521606445, 345.8415222167969)); seed.x = fract((cos(a) * 136.8168f)); @@ -610,7 +610,7 @@ describe('probability distribution plot example', () => { } fn randUniformExclusive() -> f32 { - return ((item_1() * 0.9999998f) + 1e-7f); + return ((item() * 0.9999998f) + 1e-7f); } fn randCauchy(x0: f32, gamma: f32) -> f32 { @@ -622,11 +622,11 @@ describe('probability distribution plot example', () => { return vec3f(randCauchy(0f, 1f)); } - struct item_2 { + struct dataMoreWorkersFunc_Input { @builtin(global_invocation_id) gid: vec3u, } - @compute @workgroup_size(64) fn item(input: item_2) { + @compute @workgroup_size(64) fn dataMoreWorkersFunc(input: dataMoreWorkersFunc_Input) { let id = input.gid.x; if ((id >= arrayLength(&samplesBuffer))) { return; From e9592d209278e6c97b899176a2ef1a790b0a0644 Mon Sep 17 00:00:00 2001 From: Aleksander Katan Date: Wed, 7 Jan 2026 16:58:24 +0100 Subject: [PATCH 05/11] Uncomment --- packages/typegpu/src/nameRegistry.ts | 4 ++-- .../typegpu/tests/examples/individual/jelly-slider.test.ts | 6 +++--- .../typegpu/tests/examples/individual/jelly-switch.test.ts | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/typegpu/src/nameRegistry.ts b/packages/typegpu/src/nameRegistry.ts index b97a9b30c6..05319a7d66 100644 --- a/packages/typegpu/src/nameRegistry.ts +++ b/packages/typegpu/src/nameRegistry.ts @@ -175,8 +175,8 @@ const bannedTokens = new Set([ 'yield', // Keywords that should be reserved 'sampler', - // 'uniform', - // 'storage', + 'uniform', + 'storage', ]); const builtins = new Set([ diff --git a/packages/typegpu/tests/examples/individual/jelly-slider.test.ts b/packages/typegpu/tests/examples/individual/jelly-slider.test.ts index 7e96fbdd57..3dcc7afd63 100644 --- a/packages/typegpu/tests/examples/individual/jelly-slider.test.ts +++ b/packages/typegpu/tests/examples/individual/jelly-slider.test.ts @@ -86,7 +86,7 @@ describe('jelly-slider example', () => { projInv: mat4x4f, } - @group(0) @binding(1) var uniform: Camera; + @group(0) @binding(1) var uniform_1: Camera; struct Ray { origin: vec3f, @@ -95,8 +95,8 @@ describe('jelly-slider example', () => { fn getRay(ndc: vec2f) -> Ray { var clipPos = vec4f(ndc.x, ndc.y, -1f, 1f); - let invView = (&uniform.viewInv); - let invProj = (&uniform.projInv); + let invView = (&uniform_1.viewInv); + let invProj = (&uniform_1.projInv); var viewPos = ((*invProj) * clipPos); var viewPosNormalized = vec4f((viewPos.xyz / viewPos.w), 1f); var worldPos = ((*invView) * viewPosNormalized); diff --git a/packages/typegpu/tests/examples/individual/jelly-switch.test.ts b/packages/typegpu/tests/examples/individual/jelly-switch.test.ts index 3ded3a5275..ac732e1438 100644 --- a/packages/typegpu/tests/examples/individual/jelly-switch.test.ts +++ b/packages/typegpu/tests/examples/individual/jelly-switch.test.ts @@ -60,7 +60,7 @@ describe('jelly switch example', () => { projInv: mat4x4f, } - @group(0) @binding(1) var uniform: Camera; + @group(0) @binding(1) var uniform_1: Camera; struct Ray { origin: vec3f, @@ -69,8 +69,8 @@ describe('jelly switch example', () => { fn getRay(ndc: vec2f) -> Ray { var clipPos = vec4f(ndc.x, ndc.y, -1f, 1f); - let invView = (&uniform.viewInv); - let invProj = (&uniform.projInv); + let invView = (&uniform_1.viewInv); + let invProj = (&uniform_1.projInv); var viewPos = ((*invProj) * clipPos); var viewPosNormalized = vec4f((viewPos.xyz / viewPos.w), 1f); var worldPos = ((*invView) * viewPosNormalized); From 597cc09234bfa3d2d712d3f175e9ed87127d630e Mon Sep 17 00:00:00 2001 From: Aleksander Katan Date: Fri, 9 Jan 2026 14:54:26 +0100 Subject: [PATCH 06/11] Cleanup tests --- .../typegpu/tests/unplugin/autoname.test.ts | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/packages/typegpu/tests/unplugin/autoname.test.ts b/packages/typegpu/tests/unplugin/autoname.test.ts index 8fc38565f8..e8597cfeb0 100644 --- a/packages/typegpu/tests/unplugin/autoname.test.ts +++ b/packages/typegpu/tests/unplugin/autoname.test.ts @@ -12,18 +12,14 @@ describe('autonaming', () => { const myVertexLayout = tgpu.vertexLayout((n: number) => d.arrayOf(d.i32, n) ); - - expect(getName(mySlot)).toBe('mySlot'); - expect(getName(myLayout)).toBe('myLayout'); - expect(getName(myVertexLayout)).toBe('myVertexLayout'); - }); - - it("autonames resources created using tgpu['~unstable']", () => { const myAccessor = tgpu['~unstable'].accessor(d.f32); const myPrivateVar = tgpu.privateVar(d.vec2f); const myWorkgroupVar = tgpu.workgroupVar(d.f32); const myConst = tgpu.const(d.f32, 1); + expect(getName(mySlot)).toBe('mySlot'); + expect(getName(myLayout)).toBe('myLayout'); + expect(getName(myVertexLayout)).toBe('myVertexLayout'); expect(getName(myAccessor)).toBe('myAccessor'); expect(getName(myPrivateVar)).toBe('myPrivateVar'); expect(getName(myWorkgroupVar)).toBe('myWorkgroupVar'); @@ -44,15 +40,6 @@ describe('autonaming', () => { const myReadonly = root.createReadonly(d.u32); const myUniform = root.createUniform(d.u32); const myQuerySet = root.createQuerySet('timestamp', 2); - - expect(getName(myBuffer)).toBe('myBuffer'); - expect(getName(myMutable)).toBe('myMutable'); - expect(getName(myReadonly)).toBe('myReadonly'); - expect(getName(myUniform)).toBe('myUniform'); - expect(getName(myQuerySet)).toBe('myQuerySet'); - }); - - it("autonames resources created using root['~unstable']", ({ root }) => { const myPipeline = root['~unstable'] .withCompute( tgpu['~unstable'].computeFn({ workgroupSize: [1] })(() => {}), @@ -70,6 +57,11 @@ describe('autonaming', () => { compare: 'equal', }); + expect(getName(myBuffer)).toBe('myBuffer'); + expect(getName(myMutable)).toBe('myMutable'); + expect(getName(myReadonly)).toBe('myReadonly'); + expect(getName(myUniform)).toBe('myUniform'); + expect(getName(myQuerySet)).toBe('myQuerySet'); expect(getName(myPipeline)).toBe('myPipeline'); expect(getName(myTexture)).toBe('myTexture'); expect(getName(mySampler)).toBe('mySampler'); @@ -84,7 +76,7 @@ describe('autonaming', () => { const myFn = tgpu.fn( [Item], Item, - ) /* wgsl */`(item: Item) -> Item { return item; }` + ) /* wgsl */`(item) { return item; }` .$uses({ Item }); const myLayout = tgpu .bindGroupLayout({ foo: { uniform: d.vec3f } }) From 6e0b9caaf24db0c2d587874fba4375c1e2bdeb86 Mon Sep 17 00:00:00 2001 From: Aleksander Katan Date: Fri, 9 Jan 2026 15:44:59 +0100 Subject: [PATCH 07/11] Make guarded compute pipelines namable, and autonamable --- packages/typegpu/src/core/root/init.ts | 19 +++- packages/typegpu/src/core/root/rootTypes.ts | 4 +- .../tests/guardedComputePipeline.test.ts | 31 ++++++ .../typegpu/tests/unplugin/autoname.test.ts | 5 + packages/unplugin-typegpu/src/common.ts | 2 - .../unplugin-typegpu/test/auto-naming.test.ts | 97 +++++++++++++++++++ 6 files changed, 151 insertions(+), 7 deletions(-) create mode 100644 packages/typegpu/tests/guardedComputePipeline.test.ts diff --git a/packages/typegpu/src/core/root/init.ts b/packages/typegpu/src/core/root/init.ts index 1450de4680..127878f29b 100644 --- a/packages/typegpu/src/core/root/init.ts +++ b/packages/typegpu/src/core/root/init.ts @@ -26,7 +26,7 @@ import { import { WeakMemo } from '../../memo.ts'; import { clearTextureUtilsCache } from '../texture/textureUtils.ts'; import type { Infer } from '../../shared/repr.ts'; -import { $internal } from '../../shared/symbols.ts'; +import { $getNameForward, $internal } from '../../shared/symbols.ts'; import type { AnyVertexAttribs } from '../../shared/vertexFormat.ts'; import type { ExtractBindGroupInputFromLayout, @@ -120,6 +120,7 @@ import { vec3f, vec3u } from '../../data/vector.ts'; import { u32 } from '../../data/numeric.ts'; import { ceil } from '../../std/numeric.ts'; import { allEq } from '../../std/boolean.ts'; +import { setName } from '../../shared/meta.ts'; /** * Changes the given array to a vec of 3 numbers, filling missing values with 1. @@ -194,6 +195,15 @@ export class TgpuGuardedComputePipelineImpl get sizeUniform() { return this.#sizeUniform; } + + [$internal] = true; + get [$getNameForward]() { + return this.#pipeline; + } + $name(label: string): this { + setName(this, label); + return this; + } } class WithBindingImpl implements WithBinding { @@ -253,9 +263,10 @@ class WithBindingImpl implements WithBinding { wrappedCallback(in.id.x, in.id.y, in.id.z); }`.$uses({ sizeUniform, wrappedCallback }); - const pipeline = this - .withCompute(mainCompute) - .createPipeline(); + const pipeline = (() => + this + .withCompute(mainCompute) + .createPipeline())(); return new TgpuGuardedComputePipelineImpl( root, diff --git a/packages/typegpu/src/core/root/rootTypes.ts b/packages/typegpu/src/core/root/rootTypes.ts index 664b862944..ceb21d8f80 100644 --- a/packages/typegpu/src/core/root/rootTypes.ts +++ b/packages/typegpu/src/core/root/rootTypes.ts @@ -74,12 +74,14 @@ import type { LayoutToAllowedAttribs } from '../vertexLayout/vertexAttribute.ts' import type { TgpuVertexLayout } from '../vertexLayout/vertexLayout.ts'; import type { TgpuComputeFn } from './../function/tgpuComputeFn.ts'; import type { WgslStorageTexture, WgslTexture } from '../../data/texture.ts'; +import type { TgpuNamable } from '../../shared/meta.ts'; // ---------- // Public API // ---------- -export interface TgpuGuardedComputePipeline { +export interface TgpuGuardedComputePipeline + extends TgpuNamable { /** * Returns a pipeline wrapper with the specified bind group bound. * Analogous to `TgpuComputePipeline.with(bindGroup)`. diff --git a/packages/typegpu/tests/guardedComputePipeline.test.ts b/packages/typegpu/tests/guardedComputePipeline.test.ts new file mode 100644 index 0000000000..bcfdcd7939 --- /dev/null +++ b/packages/typegpu/tests/guardedComputePipeline.test.ts @@ -0,0 +1,31 @@ +import { describe, expect } from 'vitest'; +import { it } from './utils/extendedIt.ts'; +import { getName } from '../src/shared/meta.ts'; +import { bindGroupLayout } from '../src/tgpuBindGroupLayout.ts'; +import { f32 } from '../src/data/numeric.ts'; + +describe('TgpuGuardedComputePipeline', () => { + it('can be named', ({ root }) => { + const pipeline = root.createGuardedComputePipeline(() => { + 'use gpu'; + }).$name('myPipeline'); + + expect(getName(pipeline)).toBe('myPipeline'); + expect(getName(pipeline.pipeline)).toBe('myPipeline'); + }); + + it('can be named after filling a bind group', ({ root }) => { + const myBindGroupLayout = bindGroupLayout({ a: { uniform: f32 } }); + const myBindGroup = root.createBindGroup(myBindGroupLayout, { + a: root.createBuffer(f32).$usage('uniform'), + }); + const pipeline = root.createGuardedComputePipeline(() => { + 'use gpu'; + }) + .with(myBindGroup) + .$name('myPipeline'); + + expect(getName(pipeline)).toBe('myPipeline'); + expect(getName(pipeline.pipeline)).toBe('myPipeline'); + }); +}); diff --git a/packages/typegpu/tests/unplugin/autoname.test.ts b/packages/typegpu/tests/unplugin/autoname.test.ts index e8597cfeb0..ae0a20d6bd 100644 --- a/packages/typegpu/tests/unplugin/autoname.test.ts +++ b/packages/typegpu/tests/unplugin/autoname.test.ts @@ -45,6 +45,10 @@ describe('autonaming', () => { tgpu['~unstable'].computeFn({ workgroupSize: [1] })(() => {}), ) .createPipeline(); + const myGuardedPipeline = root['~unstable'] + .createGuardedComputePipeline(() => { + 'use gpu'; + }); const myTexture = root['~unstable'].createTexture({ size: [1, 1], format: 'rgba8unorm', @@ -63,6 +67,7 @@ describe('autonaming', () => { expect(getName(myUniform)).toBe('myUniform'); expect(getName(myQuerySet)).toBe('myQuerySet'); expect(getName(myPipeline)).toBe('myPipeline'); + expect(getName(myGuardedPipeline)).toBe('myGuardedPipeline'); expect(getName(myTexture)).toBe('myTexture'); expect(getName(mySampler)).toBe('mySampler'); expect(getName(myComparisonSampler)).toBe('myComparisonSampler'); diff --git a/packages/unplugin-typegpu/src/common.ts b/packages/unplugin-typegpu/src/common.ts index 91ccbd9b2a..1d2d4344f2 100644 --- a/packages/unplugin-typegpu/src/common.ts +++ b/packages/unplugin-typegpu/src/common.ts @@ -148,7 +148,6 @@ const resourceConstructors: string[] = [ 'privateVar', 'workgroupVar', 'const', - // tgpu['~unstable'] 'slot', 'accessor', 'comptime', @@ -162,7 +161,6 @@ const resourceConstructors: string[] = [ 'createReadonly', 'createUniform', 'createQuerySet', - // root['~unstable'] 'createPipeline', 'createGuardedComputePipeline', 'createTexture', diff --git a/packages/unplugin-typegpu/test/auto-naming.test.ts b/packages/unplugin-typegpu/test/auto-naming.test.ts index 50441f5440..76414fa1ca 100644 --- a/packages/unplugin-typegpu/test/auto-naming.test.ts +++ b/packages/unplugin-typegpu/test/auto-naming.test.ts @@ -469,6 +469,53 @@ describe('[BABEL] auto naming', () => { console.log(MyController);" `); }); + + it('works with guarded pipelines', () => { + const code = `\ + import tgpu from 'typegpu'; + + const root = await tgpu.init(); + + const myGuardedPipeline = root['~unstable'] + .createGuardedComputePipeline(() => { + 'use gpu'; + }); + + const anotherGuardedPipeline = root['~unstable'] + .createGuardedComputePipeline(() => { + 'use gpu'; + }).dispatchThreads(); + + console.log(myGuardedPipeline, anotherGuardedPipeline); + `; + + expect(babelTransform(code, { autoNamingEnabled: true })) + .toMatchInlineSnapshot(` + "import tgpu from 'typegpu'; + const root = await tgpu.init(); + const myGuardedPipeline = (globalThis.__TYPEGPU_AUTONAME__ ?? (a => a))(root['~unstable'].createGuardedComputePipeline(($ => (globalThis.__TYPEGPU_META__ ??= new WeakMap()).set($.f = () => { + 'use gpu'; + }, { + v: 1, + name: void 0, + ast: {"params":[],"body":[0,[]],"externalNames":[]}, + externals: () => { + return {}; + } + }) && $.f)({})), "myGuardedPipeline"); + const anotherGuardedPipeline = (globalThis.__TYPEGPU_AUTONAME__ ?? (a => a))(root['~unstable'].createGuardedComputePipeline(($ => (globalThis.__TYPEGPU_META__ ??= new WeakMap()).set($.f = () => { + 'use gpu'; + }, { + v: 1, + name: void 0, + ast: {"params":[],"body":[0,[]],"externalNames":[]}, + externals: () => { + return {}; + } + }) && $.f)({})).dispatchThreads(), "anotherGuardedPipeline"); + console.log(myGuardedPipeline, anotherGuardedPipeline);" + `); + }); }); describe('[ROLLUP] auto naming', () => { @@ -961,4 +1008,54 @@ describe('[ROLLUP] auto naming', () => { " `); }); + + it('works with guarded pipelines', async () => { + const code = `\ + import tgpu from 'typegpu'; + + const root = await tgpu.init(); + + const myGuardedPipeline = root['~unstable'] + .createGuardedComputePipeline(() => { + 'use gpu'; + }); + + const anotherGuardedPipeline = root['~unstable'] + .createGuardedComputePipeline(() => { + 'use gpu'; + }).dispatchThreads(); + + console.log(myGuardedPipeline, anotherGuardedPipeline); + `; + + expect(await rollupTransform(code, { autoNamingEnabled: true })) + .toMatchInlineSnapshot(` + "import tgpu from 'typegpu'; + + const root = await tgpu.init(); + + const myGuardedPipeline = ((globalThis.__TYPEGPU_AUTONAME__ ?? (a => a))(root['~unstable'] + .createGuardedComputePipeline((($ => (globalThis.__TYPEGPU_META__ ??= new WeakMap()).set($.f = (() => { + 'use gpu'; + }), { + v: 1, + name: undefined, + ast: {"params":[],"body":[0,[]],"externalNames":[]}, + externals: () => ({}), + }) && $.f)({}))), "myGuardedPipeline")); + + const anotherGuardedPipeline = ((globalThis.__TYPEGPU_AUTONAME__ ?? (a => a))(root['~unstable'] + .createGuardedComputePipeline((($ => (globalThis.__TYPEGPU_META__ ??= new WeakMap()).set($.f = (() => { + 'use gpu'; + }), { + v: 1, + name: undefined, + ast: {"params":[],"body":[0,[]],"externalNames":[]}, + externals: () => ({}), + }) && $.f)({}))).dispatchThreads(), "anotherGuardedPipeline")); + + console.log(myGuardedPipeline, anotherGuardedPipeline); + " + `); + }); }); From 95498863b316b91c60916e9c1e9eb4b4835c4e57 Mon Sep 17 00:00:00 2001 From: Aleksander Katan Date: Fri, 9 Jan 2026 16:02:06 +0100 Subject: [PATCH 08/11] Clean up $name methods a little --- packages/typegpu/src/core/buffer/bufferShorthand.ts | 2 +- packages/typegpu/src/core/buffer/bufferUsage.ts | 2 +- packages/typegpu/src/core/function/tgpuComputeFn.ts | 2 +- packages/typegpu/src/core/function/tgpuFn.ts | 4 ++-- packages/typegpu/src/core/function/tgpuFragmentFn.ts | 2 +- packages/typegpu/src/core/function/tgpuVertexFn.ts | 2 +- packages/typegpu/src/core/pipeline/computePipeline.ts | 2 +- packages/typegpu/src/core/pipeline/renderPipeline.ts | 2 +- packages/typegpu/src/core/slot/accessor.ts | 4 ++-- packages/typegpu/src/shared/meta.ts | 5 ++--- packages/typegpu/src/shared/symbols.ts | 4 ++++ 11 files changed, 17 insertions(+), 14 deletions(-) diff --git a/packages/typegpu/src/core/buffer/bufferShorthand.ts b/packages/typegpu/src/core/buffer/bufferShorthand.ts index fd5ed143ff..5392edc620 100644 --- a/packages/typegpu/src/core/buffer/bufferShorthand.ts +++ b/packages/typegpu/src/core/buffer/bufferShorthand.ts @@ -99,7 +99,7 @@ export class TgpuBufferShorthandImpl< } $name(label: string): this { - setName(this[$getNameForward], label); + setName(this, label); return this; } diff --git a/packages/typegpu/src/core/buffer/bufferUsage.ts b/packages/typegpu/src/core/buffer/bufferUsage.ts index d0e14bed66..8018a69124 100644 --- a/packages/typegpu/src/core/buffer/bufferUsage.ts +++ b/packages/typegpu/src/core/buffer/bufferUsage.ts @@ -109,7 +109,7 @@ class TgpuFixedBufferImpl< } $name(label: string) { - this.buffer.$name(label); + setName(this, label); return this; } diff --git a/packages/typegpu/src/core/function/tgpuComputeFn.ts b/packages/typegpu/src/core/function/tgpuComputeFn.ts index f7f1107c2c..2457d80518 100644 --- a/packages/typegpu/src/core/function/tgpuComputeFn.ts +++ b/packages/typegpu/src/core/function/tgpuComputeFn.ts @@ -154,7 +154,7 @@ function createComputeFn>( [$internal]: true, [$getNameForward]: core, $name(newLabel: string): This { - setName(core, newLabel); + setName(this, newLabel); if (isNamable(inputType)) { inputType.$name(`${newLabel}_Input`); } diff --git a/packages/typegpu/src/core/function/tgpuFn.ts b/packages/typegpu/src/core/function/tgpuFn.ts index cd83970ce4..636efeaf46 100644 --- a/packages/typegpu/src/core/function/tgpuFn.ts +++ b/packages/typegpu/src/core/function/tgpuFn.ts @@ -179,7 +179,7 @@ function createFn( [$getNameForward]: core, $name(label: string): This { - setName(core, label); + setName(this, label); return this; }, @@ -283,7 +283,7 @@ function createBoundFunction( [$getNameForward]: innerFn, $name(label: string): This { - innerFn.$name(label); + setName(this, label); return this; }, diff --git a/packages/typegpu/src/core/function/tgpuFragmentFn.ts b/packages/typegpu/src/core/function/tgpuFragmentFn.ts index 44f222e1f6..7d06a6efdd 100644 --- a/packages/typegpu/src/core/function/tgpuFragmentFn.ts +++ b/packages/typegpu/src/core/function/tgpuFragmentFn.ts @@ -197,7 +197,7 @@ function createFragmentFn( [$internal]: true, [$getNameForward]: core, $name(newLabel: string): This { - setName(core, newLabel); + setName(this, newLabel); if (isNamable(outputType)) { outputType.$name(`${newLabel}_Output`); } diff --git a/packages/typegpu/src/core/function/tgpuVertexFn.ts b/packages/typegpu/src/core/function/tgpuVertexFn.ts index 0a260d9b80..dddef1e83e 100644 --- a/packages/typegpu/src/core/function/tgpuVertexFn.ts +++ b/packages/typegpu/src/core/function/tgpuVertexFn.ts @@ -175,7 +175,7 @@ function createVertexFn( [$internal]: true, [$getNameForward]: core, $name(newLabel: string): This { - setName(core, newLabel); + setName(this, newLabel); if (isNamable(inputType)) { inputType.$name(`${newLabel}_Input`); } diff --git a/packages/typegpu/src/core/pipeline/computePipeline.ts b/packages/typegpu/src/core/pipeline/computePipeline.ts index 9d6e6c7de2..1bd1a4cd2f 100644 --- a/packages/typegpu/src/core/pipeline/computePipeline.ts +++ b/packages/typegpu/src/core/pipeline/computePipeline.ts @@ -232,7 +232,7 @@ class TgpuComputePipelineImpl implements TgpuComputePipeline { } $name(label: string): this { - setName(this._core, label); + setName(this, label); return this; } } diff --git a/packages/typegpu/src/core/pipeline/renderPipeline.ts b/packages/typegpu/src/core/pipeline/renderPipeline.ts index 8852c8b9f5..a486499ba3 100644 --- a/packages/typegpu/src/core/pipeline/renderPipeline.ts +++ b/packages/typegpu/src/core/pipeline/renderPipeline.ts @@ -378,7 +378,7 @@ class TgpuRenderPipelineImpl implements TgpuRenderPipeline { } $name(label: string): this { - setName(this[$internal].core, label); + setName(this, label); return this; } diff --git a/packages/typegpu/src/core/slot/accessor.ts b/packages/typegpu/src/core/slot/accessor.ts index ac90544ffe..1890500dcb 100644 --- a/packages/typegpu/src/core/slot/accessor.ts +++ b/packages/typegpu/src/core/slot/accessor.ts @@ -2,7 +2,7 @@ import { schemaCallWrapper } from '../../data/schemaCallWrapper.ts'; import { type ResolvedSnippet, snip } from '../../data/snippet.ts'; import type { AnyWgslData } from '../../data/wgslTypes.ts'; import { getResolutionCtx, inCodegenMode } from '../../execMode.ts'; -import { getName } from '../../shared/meta.ts'; +import { getName, setName } from '../../shared/meta.ts'; import type { Infer, InferGPU } from '../../shared/repr.ts'; import { $getNameForward, @@ -109,7 +109,7 @@ export class TgpuAccessorImpl } $name(label: string) { - this.slot.$name(label); + setName(this, label); return this; } diff --git a/packages/typegpu/src/shared/meta.ts b/packages/typegpu/src/shared/meta.ts index 9c260b1262..9e21960f29 100644 --- a/packages/typegpu/src/shared/meta.ts +++ b/packages/typegpu/src/shared/meta.ts @@ -83,10 +83,9 @@ export function setName(definition: object, name: string): void { } /** - * Can be assigned a name. Not to be confused with - * being able to HAVE a name. + * Can be assigned a name. Not to be confused with just having a name. * The `$name` function should use `setName` to rename the object itself, - * or rename the object `$getNameForward` symbol points to instead if applicable. + * even if `$getNameForward` symbol is present. */ export interface TgpuNamable { $name(label: string): this; diff --git a/packages/typegpu/src/shared/symbols.ts b/packages/typegpu/src/shared/symbols.ts index bce790d4c9..22ea044c70 100644 --- a/packages/typegpu/src/shared/symbols.ts +++ b/packages/typegpu/src/shared/symbols.ts @@ -8,6 +8,10 @@ export const $internal = Symbol(`typegpu:${version}:$internal`); * The getter to the value of this resource, accessible on the GPU */ export const $gpuValueOf = Symbol(`typegpu:${version}:$gpuValueOf`); +/** + * If this symbol is present, this means that getName and setName + * will refer to object behind this property instead. + */ export const $getNameForward = Symbol(`typegpu:${version}:$getNameForward`); /** * Marks an object with slot-value bindings From 364de52eaaaa4cd6d9c466ff45587743083779fc Mon Sep 17 00:00:00 2001 From: Aleksander Katan Date: Fri, 9 Jan 2026 16:53:20 +0100 Subject: [PATCH 09/11] Make views namable --- packages/typegpu/src/core/texture/texture.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/typegpu/src/core/texture/texture.ts b/packages/typegpu/src/core/texture/texture.ts index 15c727f4bc..94ff1497d7 100644 --- a/packages/typegpu/src/core/texture/texture.ts +++ b/packages/typegpu/src/core/texture/texture.ts @@ -199,7 +199,7 @@ export interface TgpuTextureView< TSchema extends WgslStorageTexture | WgslTexture = | WgslStorageTexture | WgslTexture, -> { +> extends TgpuNamable { readonly [$internal]: TextureViewInternals; readonly resourceType: 'texture-view'; readonly schema: TSchema; @@ -738,13 +738,20 @@ export class TgpuLaidOutTextureViewImpl< } throw new Error( - 'Direct access to texture views values is possible only as part of a compute dispatch or draw call. Try .read() or .write() instead', + `Accessed view '${ + getName(this) ?? '' + }' outside of codegen mode. Direct access to texture views values is possible only as part of a compute dispatch or draw call. Try .read() or .write() instead`, ); } get value(): Infer { return this.$; } + + $name(label: string): this { + setName(this, label); + return this; + } } export class TgpuTextureRenderViewImpl implements TgpuTextureRenderView { From 8a4649ca304a1352081b38f1d21911ba2434d867 Mon Sep 17 00:00:00 2001 From: Aleksander Katan Date: Fri, 9 Jan 2026 16:53:42 +0100 Subject: [PATCH 10/11] Autoname views --- .../tests/examples/individual/gravity.test.ts | 4 ++-- packages/typegpu/tests/texture.test.ts | 14 ++++++++++++++ packages/typegpu/tests/unplugin/autoname.test.ts | 15 +++++++++++++++ packages/unplugin-typegpu/src/common.ts | 8 +++++--- 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/packages/typegpu/tests/examples/individual/gravity.test.ts b/packages/typegpu/tests/examples/individual/gravity.test.ts index 860b062ee0..0ed5961c19 100644 --- a/packages/typegpu/tests/examples/individual/gravity.test.ts +++ b/packages/typegpu/tests/examples/individual/gravity.test.ts @@ -200,7 +200,7 @@ describe('gravity example', () => { return skyBoxVertex_Output((camera.projection * vec4f(viewPos, 1f)), input.position.xyz); } - @group(0) @binding(1) var item: texture_cube; + @group(0) @binding(1) var skyBox: texture_cube; @group(0) @binding(2) var sampler_1: sampler; @@ -209,7 +209,7 @@ describe('gravity example', () => { } @fragment fn skyBoxFragment(input: skyBoxFragment_Input) -> @location(0) vec4f { - return textureSample(item, sampler_1, normalize(input.texCoord)); + return textureSample(skyBox, sampler_1, normalize(input.texCoord)); } struct CelestialBody { diff --git a/packages/typegpu/tests/texture.test.ts b/packages/typegpu/tests/texture.test.ts index ad4fd5894c..be03c53b87 100644 --- a/packages/typegpu/tests/texture.test.ts +++ b/packages/typegpu/tests/texture.test.ts @@ -13,6 +13,7 @@ import * as d from '../src/data/index.ts'; import './utils/webgpuGlobals.ts'; import { attest } from '@ark/attest'; import tgpu from '../src/index.ts'; +import { getName } from '../src/shared/meta.ts'; describe('TgpuTexture', () => { it('makes passing the default, `undefined` or omitting an option prop result in the same type.', ({ root }) => { @@ -176,6 +177,19 @@ describe('TgpuTexture', () => { .$usage('storage'); }); + it('creates namable views', ({ root }) => { + const texture = root + .createTexture({ + size: [512, 512, 12], + format: 'rgba8unorm', + }) + .$usage('sampled'); + + const sampled1 = texture.createView(d.texture2d(d.i32)).$name('myView'); + + expect(getName(sampled1)).toBe('myView'); + }); + it('creates a sampled texture view with correct type', ({ root }) => { const texture = root .createTexture({ diff --git a/packages/typegpu/tests/unplugin/autoname.test.ts b/packages/typegpu/tests/unplugin/autoname.test.ts index ae0a20d6bd..d5dd1f1a35 100644 --- a/packages/typegpu/tests/unplugin/autoname.test.ts +++ b/packages/typegpu/tests/unplugin/autoname.test.ts @@ -92,6 +92,21 @@ describe('autonaming', () => { expect(getName(myLayout)).toBe('myLayout'); }); + it('names views', ({ root }) => { + const texture = root['~unstable'].createTexture({ + size: [256, 256], + format: 'rgba8unorm', + }).$usage('sampled', 'storage'); + + const sampledView = texture.createView(d.texture2d(d.f32)); + const storageView = texture.createView( + d.textureStorage2d('rgba8unorm', 'read-only'), + ); + + expect(getName(sampledView)).toBe('sampledView'); + expect(getName(storageView)).toBe('storageView'); + }); + it('does not rename already named resources', () => { const myStruct = d.struct({ a: d.u32 }).$name('IntStruct'); const myFunction = tgpu.fn([])(() => 0).$name('ConstFunction'); diff --git a/packages/unplugin-typegpu/src/common.ts b/packages/unplugin-typegpu/src/common.ts index 1d2d4344f2..ed7ac6c569 100644 --- a/packages/unplugin-typegpu/src/common.ts +++ b/packages/unplugin-typegpu/src/common.ts @@ -152,9 +152,6 @@ const resourceConstructors: string[] = [ 'accessor', 'comptime', ...fnShellFunctionNames, - // d - 'struct', - 'unstruct', // root 'createBuffer', 'createMutable', @@ -166,6 +163,11 @@ const resourceConstructors: string[] = [ 'createTexture', 'createSampler', 'createComparisonSampler', + // d + 'struct', + 'unstruct', + // other + 'createView', ]; /** From e218f449fd578ecd3a0d212349a4dfce7d90e0c4 Mon Sep 17 00:00:00 2001 From: Aleksander Katan Date: Fri, 9 Jan 2026 17:18:20 +0100 Subject: [PATCH 11/11] smol --- packages/typegpu/src/core/root/init.ts | 1 + packages/typegpu/tests/unplugin/autoname.test.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/typegpu/src/core/root/init.ts b/packages/typegpu/src/core/root/init.ts index 127878f29b..ba1a35949b 100644 --- a/packages/typegpu/src/core/root/init.ts +++ b/packages/typegpu/src/core/root/init.ts @@ -263,6 +263,7 @@ class WithBindingImpl implements WithBinding { wrappedCallback(in.id.x, in.id.y, in.id.z); }`.$uses({ sizeUniform, wrappedCallback }); + // NOTE: in certain setups, unplugin can run on package typegpu, so we have to avoid auto-naming triggering here const pipeline = (() => this .withCompute(mainCompute) diff --git a/packages/typegpu/tests/unplugin/autoname.test.ts b/packages/typegpu/tests/unplugin/autoname.test.ts index d5dd1f1a35..9c8d45f50a 100644 --- a/packages/typegpu/tests/unplugin/autoname.test.ts +++ b/packages/typegpu/tests/unplugin/autoname.test.ts @@ -248,7 +248,7 @@ describe('autonaming', () => { expect(getName(myController.myBuffer)).toBe('myBuffer'); }); - it('autonames this private prop assignment', ({ root }) => { + it('autonames private prop assignment', ({ root }) => { class MyController { #myBuffer;