Skip to content
Draft
Changes from all commits
Commits
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
174 changes: 174 additions & 0 deletions packages/typegpu/tests/tgsl/referenceConsumption.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import { describe, expect } from 'vitest';
import { it } from 'typegpu-testing-utility';
import tgpu, { d } from '../../src/index.js';

describe('reference consumption', () => {
const Boid = d.struct({ pos: d.vec3f, vel: d.vec3f });
const layout = tgpu.bindGroupLayout({
boids: { storage: d.arrayOf(Boid, 10), access: 'mutable' },
});

describe('successful single consumption', () => {
it('allows assigning a local variable reference to a storage buffer element', () => {
const main = () => {
'use gpu';
const boid = Boid({ pos: d.vec3f(1, 2, 3), vel: d.vec3f(4, 5, 6) });
layout.$.boids[0] = boid;
};

expect(tgpu.resolve([main])).toMatchInlineSnapshot();
});

it('allows assigning a reference read from one slot to another', () => {
const layout = tgpu.bindGroupLayout({
src: { storage: d.arrayOf(d.vec3f, 10) },
dst: { storage: d.arrayOf(d.vec3f, 10), access: 'mutable' },
});

const main = () => {
'use gpu';
const pos = layout.$.src[0]!;
layout.$.dst[0] = pos;
};

expect(tgpu.resolve([main])).toMatchInlineSnapshot();
});
});

describe('mutation after consumption', () => {
it('fails when mutating a consumed reference (assignment)', () => {
const main = () => {
'use gpu';
const boid = Boid({ pos: d.vec3f(1, 2, 3), vel: d.vec3f(4, 5, 6) });
layout.$.boids[0] = boid;
boid.pos = d.vec3f(7, 8, 9);
};

expect(() => tgpu.resolve([main])).toThrowErrorMatchingInlineSnapshot();

Check failure on line 47 in packages/typegpu/tests/tgsl/referenceConsumption.test.ts

View workflow job for this annotation

GitHub Actions / build-and-test

[typegpu] tests/tgsl/referenceConsumption.test.ts > reference consumption > mutation after consumption > fails when mutating a consumed reference (assignment)

Error: Snapshot `reference consumption > mutation after consumption > fails when mutating a consumed reference (assignment) 1` mismatched ❯ tests/tgsl/referenceConsumption.test.ts:47:42
});

it('fails when mutating a consumed reference (simple modification)', () => {
const main = () => {
'use gpu';
const boid = Boid({ pos: d.vec3f(1, 2, 3), vel: d.vec3f(4, 5, 6) });
layout.$.boids[0] = boid;
boid.pos.x += 7;
};

expect(() => tgpu.resolve([main])).toThrowErrorMatchingInlineSnapshot();

Check failure on line 58 in packages/typegpu/tests/tgsl/referenceConsumption.test.ts

View workflow job for this annotation

GitHub Actions / build-and-test

[typegpu] tests/tgsl/referenceConsumption.test.ts > reference consumption > mutation after consumption > fails when mutating a consumed reference (simple modification)

Error: Snapshot `reference consumption > mutation after consumption > fails when mutating a consumed reference (simple modification) 1` mismatched ❯ tests/tgsl/referenceConsumption.test.ts:58:42
});
});

describe('double consumption', () => {
it('fails when assigning the same reference twice', () => {
const main = () => {
'use gpu';
const boid = Boid({ pos: d.vec3f(1, 2, 3), vel: d.vec3f(4, 5, 6) });
layout.$.boids[0] = boid;
layout.$.boids[1] = boid;
};

expect(() => tgpu.resolve([main])).toThrowErrorMatchingInlineSnapshot();

Check failure on line 71 in packages/typegpu/tests/tgsl/referenceConsumption.test.ts

View workflow job for this annotation

GitHub Actions / build-and-test

[typegpu] tests/tgsl/referenceConsumption.test.ts > reference consumption > double consumption > fails when assigning the same reference twice

Error: Snapshot `reference consumption > double consumption > fails when assigning the same reference twice 1` mismatched ❯ tests/tgsl/referenceConsumption.test.ts:71:42
});

it('fails when returning a consumed reference', () => {
const main = () => {
'use gpu';
const boid = Boid({ pos: d.vec3f(1, 2, 3), vel: d.vec3f(4, 5, 6) });
layout.$.boids[0] = boid;
return boid;
};

expect(() => tgpu.resolve([main])).toThrowErrorMatchingInlineSnapshot();

Check failure on line 82 in packages/typegpu/tests/tgsl/referenceConsumption.test.ts

View workflow job for this annotation

GitHub Actions / build-and-test

[typegpu] tests/tgsl/referenceConsumption.test.ts > reference consumption > double consumption > fails when returning a consumed reference

Error: Snapshot `reference consumption > double consumption > fails when returning a consumed reference 1` mismatched ❯ tests/tgsl/referenceConsumption.test.ts:82:42
});
});

describe('consumption in loops', () => {
const layout = tgpu.bindGroupLayout({
positions: { storage: d.arrayOf(d.vec3f, 10), access: 'mutable' },
});

it('fails when consuming a reference inside a for loop', () => {
const main = () => {
'use gpu';
const pos = d.vec3f(1, 2, 3);
for (let i = 0; i < 10; i++) {
layout.$.positions[i] = pos;
}
};

expect(() => tgpu.resolve([main])).toThrowErrorMatchingInlineSnapshot();

Check failure on line 100 in packages/typegpu/tests/tgsl/referenceConsumption.test.ts

View workflow job for this annotation

GitHub Actions / build-and-test

[typegpu] tests/tgsl/referenceConsumption.test.ts > reference consumption > consumption in loops > fails when consuming a reference inside a for loop

Error: Snapshot `reference consumption > consumption in loops > fails when consuming a reference inside a for loop 1` mismatched ❯ tests/tgsl/referenceConsumption.test.ts:100:42
});

it('fails when consuming a reference inside a while loop', () => {
const main = () => {
'use gpu';
const pos = d.vec3f(1, 2, 3);
let i = 0;
while (i < 10) {
layout.$.positions[i] = pos;
i += 1;
}
};

expect(() => tgpu.resolve([main])).toThrowErrorMatchingInlineSnapshot();

Check failure on line 114 in packages/typegpu/tests/tgsl/referenceConsumption.test.ts

View workflow job for this annotation

GitHub Actions / build-and-test

[typegpu] tests/tgsl/referenceConsumption.test.ts > reference consumption > consumption in loops > fails when consuming a reference inside a while loop

Error: Snapshot `reference consumption > consumption in loops > fails when consuming a reference inside a while loop 1` mismatched ❯ tests/tgsl/referenceConsumption.test.ts:114:42
});
});

describe('consumption in branches', () => {
it('fails when mutating a reference consumed in an if branch', () => {
const testFn = tgpu.fn([d.bool])((cond) => {
const boid = Boid({ pos: d.vec3f(1, 2, 3), vel: d.vec3f(4, 5, 6) });
if (cond) {
layout.$.boids[0] = boid;
}
boid.pos = d.vec3f(7, 8, 9);
});

expect(() => tgpu.resolve([testFn])).toThrowErrorMatchingInlineSnapshot();

Check failure on line 128 in packages/typegpu/tests/tgsl/referenceConsumption.test.ts

View workflow job for this annotation

GitHub Actions / build-and-test

[typegpu] tests/tgsl/referenceConsumption.test.ts > reference consumption > consumption in branches > fails when mutating a reference consumed in an if branch

Error: Snapshot `reference consumption > consumption in branches > fails when mutating a reference consumed in an if branch 1` mismatched ❯ tests/tgsl/referenceConsumption.test.ts:128:44
});

it('allows mutating a reference consumed in a pruned if branch', () => {
const testFn = tgpu.fn([d.bool])((cond) => {
const boid = Boid({ pos: d.vec3f(1, 2, 3), vel: d.vec3f(4, 5, 6) });
if (false) {
layout.$.boids[0] = boid;
}
boid.pos = d.vec3f(7, 8, 9);
});

expect(tgpu.resolve([testFn])).toMatchInlineSnapshot();

Check failure on line 140 in packages/typegpu/tests/tgsl/referenceConsumption.test.ts

View workflow job for this annotation

GitHub Actions / build-and-test

[typegpu] tests/tgsl/referenceConsumption.test.ts > reference consumption > consumption in branches > allows mutating a reference consumed in a pruned if branch

Error: Snapshot `reference consumption > consumption in branches > allows mutating a reference consumed in a pruned if branch 1` mismatched ❯ tests/tgsl/referenceConsumption.test.ts:140:38
});

it('allows consumption and mutation in disjoint branches', () => {
const testFn = tgpu.fn([d.bool])((cond) => {
const boid = Boid({ pos: d.vec3f(1, 2, 3), vel: d.vec3f(4, 5, 6) });
if (cond) {
layout.$.boids[0] = boid;
} else {
boid.pos = d.vec3f(7, 8, 9);
}
});

expect(tgpu.resolve([testFn])).toMatchInlineSnapshot();
});
});

describe('non-mutating use after consumption', () => {
it('allows passing a consumed reference as a by-value function argument', () => {
const readPosition = (boid: d.Infer<typeof Boid>) => {
'use gpu';
return boid.pos;
};

const main = () => {
'use gpu';
const boid = Boid({ pos: d.vec3f(1, 2, 3), vel: d.vec3f(4, 5, 6) });
layout.$.boids[0] = boid;
const pos = readPosition(boid);
};

expect(tgpu.resolve([main])).toMatchInlineSnapshot();
});
});
});
Loading