diff --git a/packages/typegpu/src/core/slot/accessor.ts b/packages/typegpu/src/core/slot/accessor.ts index 321f866b29..846dab496f 100644 --- a/packages/typegpu/src/core/slot/accessor.ts +++ b/packages/typegpu/src/core/slot/accessor.ts @@ -2,7 +2,7 @@ import { type AnyData, isData } from '../../data/dataTypes.ts'; import { schemaCallWrapper } from '../../data/schemaCallWrapper.ts'; import { isSnippet, type ResolvedSnippet, snip } from '../../data/snippet.ts'; import type { BaseData } from '../../data/wgslTypes.ts'; -import { getResolutionCtx, inCodegenMode } from '../../execMode.ts'; +import { getResolutionCtx } from '../../execMode.ts'; import { getName, hasTinyestMetadata, setName } from '../../shared/meta.ts'; import type { InferGPU } from '../../shared/repr.ts'; import { @@ -174,7 +174,7 @@ export class TgpuAccessorImpl } get $(): InferGPU { - if (inCodegenMode()) { + if (getResolutionCtx()) { return this[$gpuValueOf]; } @@ -198,7 +198,7 @@ export class TgpuMutableAccessorImpl } get $(): InferGPU { - if (inCodegenMode()) { + if (getResolutionCtx()) { return this[$gpuValueOf]; } diff --git a/packages/typegpu/tests/tgsl/comptime.test.ts b/packages/typegpu/tests/tgsl/comptime.test.ts index f4fc57f42c..9bc061c97b 100644 --- a/packages/typegpu/tests/tgsl/comptime.test.ts +++ b/packages/typegpu/tests/tgsl/comptime.test.ts @@ -75,4 +75,69 @@ describe('comptime', () => { }" `); }); + + it('can read accessors during shader resolution', () => { + const value = tgpu.accessor(d.f32, 1); + const readValue = tgpu.comptime(() => value.$); + + const myFn = tgpu.fn( + [], + d.f32, + )(() => { + return readValue(); + }); + + expect(tgpu.resolve([myFn])).toMatchInlineSnapshot(` + "fn myFn() -> f32 { + return 1f; + }" + `); + + expect(tgpu.resolve([myFn.with(value, 2)])).toMatchInlineSnapshot(` + "fn myFn() -> f32 { + return 2f; + }" + `); + }); + + it('can read and work with accessors in comptime', () => { + const valueAccess = tgpu.accessor(d.f32, 1); + const doubleValue = tgpu.comptime(() => valueAccess.$ * 2); + + const myFn = tgpu.fn( + [], + d.f32, + )(() => { + return doubleValue(); + }); + + expect(tgpu.resolve([myFn])).toMatchInlineSnapshot(` + "fn myFn() -> f32 { + return NaNf; + }" + `); + + expect(tgpu.resolve([myFn.with(valueAccess, 2)])).toMatchInlineSnapshot(` + "fn myFn() -> f32 { + return NaNf; + }" + `); + }); + + it('throws when a comptime-read accessor has no value', () => { + const value = tgpu.accessor(d.f32); + const readValue = tgpu.comptime(() => value.$); + const myFn = () => { + 'use gpu'; + return readValue(); + }; + + expect(() => tgpu.resolve([myFn])).toThrowErrorMatchingInlineSnapshot(` + [Error: Resolution of the following tree failed: + - + - fn*:myFn + - fn*:myFn() + - fn:readValue: Missing value for 'slot:value'] + `); + }); });