-
-
Notifications
You must be signed in to change notification settings - Fork 66
feat: isBeingTranspiled + getTargetShaderLanguage #2518
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: impr/infix-dispatch-handling
Are you sure you want to change the base?
Changes from all commits
a0d7d65
046dddd
032770d
b18b174
e33e60a
b898584
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,62 @@ | ||||||
| import { comptime } from '../core/function/comptime.ts'; | ||||||
| import { bool } from '../data/numeric.ts'; | ||||||
| import { snip } from '../data/snippet.ts'; | ||||||
| import { getExecMode, getResolutionCtx } from '../execMode.ts'; | ||||||
| import { $gpuCallable } from '../shared/symbols.ts'; | ||||||
| import type { DualFn } from '../types.ts'; | ||||||
|
|
||||||
| const impl = (() => false) as DualFn<() => boolean>; | ||||||
| impl.toString = () => 'isBeingTranspiled'; | ||||||
| impl[$gpuCallable] = { | ||||||
| call(_ctx, _args) { | ||||||
| return snip(true, bool, 'constant'); | ||||||
| }, | ||||||
| }; | ||||||
|
|
||||||
| /** | ||||||
| * Returns `true` when the direct callee is being transpiled for GPU, otherwise `false`. | ||||||
| * | ||||||
| * @example | ||||||
| * const f = () => { | ||||||
| * 'use gpu'; | ||||||
| * return isBeingTranspiled() ? 1 : 0; | ||||||
| * }; | ||||||
| * | ||||||
| * f() // returns 0, but resolved WGSL looks like this: | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit
Suggested change
|
||||||
| * | ||||||
| * fn f() -> i32 { | ||||||
| * return 1; | ||||||
| * } | ||||||
| * | ||||||
| * @note | ||||||
| * Inside `comptime`, `lazy` or `simulate`, it always returns `false`. | ||||||
| */ | ||||||
| export const isBeingTranspiled = impl; | ||||||
|
|
||||||
| /** | ||||||
| * Returns `wgsl` if invoked during the resolution process; otherwise, returns `undefined`. | ||||||
| * | ||||||
| * @example | ||||||
| * const f = () => { | ||||||
| * 'use gpu'; | ||||||
| * return getTargetShaderLanguage() === 'wgsl'; | ||||||
| * }; | ||||||
| * | ||||||
| * f() // returns false, but resolved WGSL looks like this: | ||||||
| * | ||||||
| * fn f() -> bool { | ||||||
| * return true; | ||||||
| * } | ||||||
| * | ||||||
| * @note | ||||||
| * Inside `lazy`, it always returns `wgsl`. | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Until now I didn't know lazy is not callable in JS. What no docs does to a man. Can we mention it here?
Suggested change
|
||||||
| * Inside `simulate`, it always returns `undefined`. | ||||||
| * Inside `comptime`, it returns `wgsl` if called during the resolution process; otherwise, `undefined`. | ||||||
| */ | ||||||
| export const getTargetShaderLanguage = comptime((() => { | ||||||
| const ctx = getResolutionCtx(); | ||||||
| if (!ctx) { | ||||||
| return undefined; | ||||||
| } | ||||||
| return getExecMode().type !== 'simulate' ? 'wgsl' : undefined; | ||||||
| }) as () => string | undefined); | ||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,172 @@ | ||||||
| import { it } from 'typegpu-testing-utility'; | ||||||
| import { expect, describe } from 'vitest'; | ||||||
|
|
||||||
| import tgpu, { d, std } from '../../src/index.js'; | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| describe('isBeingTranspiled', () => { | ||||||
| it('returns false top level', () => { | ||||||
| expect(std.isBeingTranspiled()).toBe(false); | ||||||
| }); | ||||||
|
|
||||||
| it('returns true during function resolution', () => { | ||||||
| const f = () => { | ||||||
| 'use gpu'; | ||||||
| if (std.isBeingTranspiled()) { | ||||||
| return 7; | ||||||
| } else { | ||||||
| return -7; | ||||||
| } | ||||||
| }; | ||||||
|
|
||||||
| expect(tgpu.resolve([f])).toMatchInlineSnapshot(` | ||||||
| "fn f() -> i32 { | ||||||
| { | ||||||
| return 7; | ||||||
| } | ||||||
| }" | ||||||
| `); | ||||||
| }); | ||||||
|
|
||||||
| it('returns false inside comptime', () => { | ||||||
| const checkTranspilation = tgpu.comptime(std.isBeingTranspiled); | ||||||
| expect(checkTranspilation()).toBe(false); | ||||||
|
|
||||||
| const f = () => { | ||||||
| 'use gpu'; | ||||||
| const _transpilation = checkTranspilation(); | ||||||
| }; | ||||||
|
|
||||||
| expect(tgpu.resolve([f])).toMatchInlineSnapshot(` | ||||||
| "fn f() { | ||||||
| const _transpilation = false; | ||||||
| }" | ||||||
| `); | ||||||
|
|
||||||
| expect(checkTranspilation()).toBe(false); | ||||||
| }); | ||||||
|
|
||||||
| it('returns false inside lazy', () => { | ||||||
| const checkTranspilation = tgpu.lazy(std.isBeingTranspiled); | ||||||
|
|
||||||
| const f = () => { | ||||||
| 'use gpu'; | ||||||
| const _transpilation = checkTranspilation.$; | ||||||
| }; | ||||||
|
|
||||||
| expect(tgpu.resolve([f])).toMatchInlineSnapshot(` | ||||||
| "fn f() { | ||||||
| const _transpilation = false; | ||||||
| }" | ||||||
| `); | ||||||
| }); | ||||||
|
|
||||||
| it('returns false inside simulate', () => { | ||||||
| const counter = tgpu.privateVar(d.u32, 0); | ||||||
|
|
||||||
| const result = tgpu['~unstable'].simulate(() => { | ||||||
| if (!std.isBeingTranspiled()) { | ||||||
| counter.$ += 1; | ||||||
| } | ||||||
| return counter.$; | ||||||
| }); | ||||||
|
|
||||||
| expect(result.value).toBe(1); | ||||||
| }); | ||||||
|
|
||||||
| it('correctly branches during js execution', () => { | ||||||
| const f = () => { | ||||||
| 'use gpu'; | ||||||
| if (std.isBeingTranspiled()) { | ||||||
| return 7; | ||||||
| } else { | ||||||
| return -7; | ||||||
| } | ||||||
| }; | ||||||
|
|
||||||
| expect(f()).toBe(-7); | ||||||
| }); | ||||||
| }); | ||||||
|
|
||||||
| describe('getTargetShaderLanguage', () => { | ||||||
| it('returns undefined top level', () => { | ||||||
| expect(std.getTargetShaderLanguage()).toBe(undefined); | ||||||
| }); | ||||||
|
|
||||||
| it('returns `wgsl` during function resolution', () => { | ||||||
| const f = () => { | ||||||
| 'use gpu'; | ||||||
| if (std.getTargetShaderLanguage() === 'wgsl') { | ||||||
| return 7; | ||||||
| } else { | ||||||
| return -7; | ||||||
| } | ||||||
| }; | ||||||
|
|
||||||
| expect(tgpu.resolve([f])).toMatchInlineSnapshot(` | ||||||
| "fn f() -> i32 { | ||||||
| { | ||||||
| return 7; | ||||||
| } | ||||||
| }" | ||||||
| `); | ||||||
| }); | ||||||
|
|
||||||
| it('returns undefined inside comptime outside of resolution and `wgsl` during function resolution', () => { | ||||||
| const checkTranspilation = tgpu.comptime(std.getTargetShaderLanguage); | ||||||
| expect(checkTranspilation()).toBe(undefined); | ||||||
|
|
||||||
| const f = () => { | ||||||
| 'use gpu'; | ||||||
| const _transpilation = checkTranspilation() === 'wgsl'; | ||||||
| }; | ||||||
|
|
||||||
| expect(tgpu.resolve([f])).toMatchInlineSnapshot(` | ||||||
| "fn f() { | ||||||
| const _transpilation = true; | ||||||
| }" | ||||||
| `); | ||||||
|
|
||||||
| expect(checkTranspilation()).toBe(undefined); | ||||||
| }); | ||||||
|
|
||||||
| it('returns `wgsl` inside lazy', () => { | ||||||
| const checkTranspilation = tgpu.lazy(std.getTargetShaderLanguage); | ||||||
|
|
||||||
| const f = () => { | ||||||
| 'use gpu'; | ||||||
| const _transpilation = checkTranspilation.$ === 'wgsl'; | ||||||
| }; | ||||||
|
|
||||||
| expect(tgpu.resolve([f])).toMatchInlineSnapshot(` | ||||||
| "fn f() { | ||||||
| const _transpilation = true; | ||||||
| }" | ||||||
| `); | ||||||
| }); | ||||||
|
|
||||||
| it('returns undefined inside simulate', () => { | ||||||
| const counter = tgpu.privateVar(d.u32, 0); | ||||||
|
|
||||||
| const result = tgpu['~unstable'].simulate(() => { | ||||||
| if (std.getTargetShaderLanguage() !== 'wgsl') { | ||||||
| counter.$ += 1; | ||||||
| } | ||||||
| return counter.$; | ||||||
| }); | ||||||
|
|
||||||
| expect(result.value).toBe(1); | ||||||
| }); | ||||||
|
|
||||||
| it('correctly branches during js execution', () => { | ||||||
| const f = () => { | ||||||
| 'use gpu'; | ||||||
| if (std.getTargetShaderLanguage() === 'wgsl') { | ||||||
| return 7; | ||||||
| } else { | ||||||
| return -7; | ||||||
| } | ||||||
| }; | ||||||
|
|
||||||
| expect(f()).toBe(-7); | ||||||
| }); | ||||||
| }); | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we use
coerceToSnippethere? This will allow future snippet properties to be properly applied, like side effects.