diff --git a/apps/typegpu-docs/src/content/docs/apis/utils.mdx b/apps/typegpu-docs/src/content/docs/apis/utils.mdx index 3d9060a32e..534e4b0769 100644 --- a/apps/typegpu-docs/src/content/docs/apis/utils.mdx +++ b/apps/typegpu-docs/src/content/docs/apis/utils.mdx @@ -111,7 +111,8 @@ Use an `if` statement for those cases. TypeGPU exposes two standard-library probes for code that needs to adapt to its execution environment: - `std.isBeingTranspiled()` tells a direct `'use gpu'` callee whether it is currently being transpiled. -- `std.getTargetShaderLanguage()` returns `'wgsl'` during WGSL resolution and `undefined` otherwise. +- `std.getTargetShaderLanguage()` returns the name of the shader language being generated (usually `'wgsl'`) + if it's called during shader generation, and `undefined` otherwise. ```ts twoslash import { tgpu, d, std } from 'typegpu'; @@ -130,9 +131,9 @@ Their behavior in each environment is: | Environment | `isBeingTranspiled()` | `getTargetShaderLanguage()` | | --- | --- | --- | | Normal JavaScript | `false` | `undefined` | -| Direct `'use gpu'` callee being transpiled | `true` | `'wgsl'` | -| Inside `tgpu.comptime` | `false` | `'wgsl'` during resolution; otherwise `undefined` | -| Inside `tgpu.lazy` | `false` | `'wgsl'` | +| Direct `'use gpu'` callee being transpiled | `true` | name of the shader language, e.g. `'wgsl'` | +| Inside `tgpu.comptime` | `false` | during resolution, name of the shader language, e.g. `'wgsl'`; otherwise `undefined` | +| Inside `tgpu.lazy` | `false` | name of the shader language, e.g. `'wgsl'` | | Inside `tgpu['~unstable'].simulate` | `false` | `undefined` | These probes are intended for environment-specific implementation choices. diff --git a/packages/typegpu-gl/src/glslGenerator.ts b/packages/typegpu-gl/src/glslGenerator.ts index 82850c284e..c240b942e1 100644 --- a/packages/typegpu-gl/src/glslGenerator.ts +++ b/packages/typegpu-gl/src/glslGenerator.ts @@ -84,6 +84,10 @@ export class GlslGenerator extends WgslGenerator { #functionType: TgpuShaderStage | 'normal' | undefined; #entryFnState: EntryFnState | undefined; + static { + GlslGenerator.prototype.languageKey = 'glsl'; + } + override typeAnnotation(data: d.BaseData): string { // For WGSL identity types (scalars, vectors, common matrices), map to GLSL directly. if (!d.isLooseData(data)) { diff --git a/packages/typegpu-gl/tests/glslGenerator.test.ts b/packages/typegpu-gl/tests/glslGenerator.test.ts index e72a8d7d03..c0f67f7936 100644 --- a/packages/typegpu-gl/tests/glslGenerator.test.ts +++ b/packages/typegpu-gl/tests/glslGenerator.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest'; -import { tgpu, d } from 'typegpu'; +import { tgpu, d, std } from 'typegpu'; import { glOptions } from '@typegpu/gl'; import { translateWgslTypeToGlsl } from '../src/glslGenerator.ts'; @@ -47,6 +47,21 @@ describe('translateWgslTypeToGlsl', () => { }); }); +describe('GlslGenerator', () => { + it('reports "glsl" as the language', () => { + function foo() { + 'use gpu'; + return std.getTargetShaderLanguage() === 'glsl'; + } + + expect(tgpu.resolve([foo], glOptions())).toMatchInlineSnapshot(` + "bool foo() { + return true; + }" + `); + }); +}); + describe('GlslGenerator - variable declarations', () => { it('generates GLSL-style variable declarations for JS function', () => { const main = () => { diff --git a/packages/typegpu/src/std/environment.ts b/packages/typegpu/src/std/environment.ts index 411c125eec..5b26bd0d45 100644 --- a/packages/typegpu/src/std/environment.ts +++ b/packages/typegpu/src/std/environment.ts @@ -33,10 +33,11 @@ impl[$gpuCallable] = { export const isBeingTranspiled = impl; /** - * Returns `wgsl` if invoked during the resolution process; otherwise, returns `undefined`. + * If invoked during the resolution process, it returns the name of the shader language that + * is ultimately being generated (usually `wgsl`); otherwise, returns `undefined`. * * @example - * const f = () => { + * function f() { * 'use gpu'; * return getTargetShaderLanguage() === 'wgsl'; * }; @@ -48,14 +49,15 @@ export const isBeingTranspiled = impl; * } * * @note - * Inside `lazy`, it always returns `wgsl`. * Inside `simulate`, it always returns `undefined`. - * Inside `comptime`, it returns `wgsl` if called during the resolution process; otherwise, `undefined`. + * + * Inside `comptime`, it returns the shader language that is ultimately + * being generated (usually `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; + return getExecMode().type !== 'simulate' ? ctx.gen.languageKey : undefined; }) as () => string | undefined); diff --git a/packages/typegpu/src/tgsl/shaderGenerator.ts b/packages/typegpu/src/tgsl/shaderGenerator.ts index 04ee023ccd..351d4ccf99 100644 --- a/packages/typegpu/src/tgsl/shaderGenerator.ts +++ b/packages/typegpu/src/tgsl/shaderGenerator.ts @@ -37,6 +37,8 @@ export interface VariableDefinitionOptions { * shader code in the target language (WGSL, GLSL, etc.). */ export interface ShaderGenerator { + readonly languageKey: string; + initGenerator(ctx: GenerationCtx): void; declareGlobalConst(options: ConstantDefinitionOptions): ResolvedSnippet; diff --git a/packages/typegpu/src/tgsl/wgslGenerator.ts b/packages/typegpu/src/tgsl/wgslGenerator.ts index 1399436130..57577869a9 100644 --- a/packages/typegpu/src/tgsl/wgslGenerator.ts +++ b/packages/typegpu/src/tgsl/wgslGenerator.ts @@ -213,6 +213,13 @@ export class WgslGenerator implements ShaderGenerator { // used to detect `continue` and `break` nodes in loop body #unrolling = false; + // prototype properties + declare languageKey: string; + + static { + WgslGenerator.prototype.languageKey = 'wgsl'; + } + public initGenerator(ctx: GenerationCtx) { this.#ctx = ctx; }