Skip to content

Commit f6cba7a

Browse files
committed
More GLSL generation
1 parent 80275bf commit f6cba7a

File tree

4 files changed

+113
-6
lines changed

4 files changed

+113
-6
lines changed

packages/typegpu-glsl/src/index.ts

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,78 @@
11
import { type ShaderGenerator, type Snippet, WgslGenerator } from 'typegpu';
22
import type * as tinyest from 'tinyest';
3+
import type { AnyData } from 'typegpu/data';
4+
5+
const wgslToGlslTypeMap = {
6+
f32: 'float',
7+
f64: 'double',
8+
i32: 'int',
9+
u32: 'uint',
10+
void: 'void',
11+
};
12+
13+
function resolveSchema(
14+
ctx: ShaderGenerator.ResolutionCtx,
15+
schema: AnyData,
16+
): { typePrefix: string; typeSuffix: string } {
17+
if (schema.type in wgslToGlslTypeMap) {
18+
return {
19+
typePrefix:
20+
wgslToGlslTypeMap[schema.type as keyof typeof wgslToGlslTypeMap],
21+
typeSuffix: '',
22+
};
23+
}
24+
25+
if (schema.type === 'array') {
26+
return {
27+
typePrefix: resolveSchema(ctx, schema.elementType as AnyData).typePrefix,
28+
typeSuffix: `[${schema.length}]`,
29+
};
30+
}
31+
32+
// TODO: Make struct declaration the responsibility of the
33+
// shader generator
34+
// if (schema.type === 'struct') {
35+
// ctx.addDeclaration();
36+
37+
// const fields = schema.fields.map((field) =>
38+
// `${resolveSchema(ctx, field.type).typePrefix} ${field.name}`
39+
// ).join(', ');
40+
// return {
41+
// typePrefix: `struct ${structName} { ${fields} }`,
42+
// typeSuffix: '',
43+
// };
44+
// }
45+
46+
throw new Error(`Unsupported type: ${String(schema)}`);
47+
}
348

449
export class GLSLShaderGenerator extends WgslGenerator
550
implements ShaderGenerator {
651
public override expression(expression: tinyest.Expression): Snippet {
752
return super.expression(expression);
853
}
954

10-
public override functionBody(bodyNode: tinyest.Block): string {
11-
return 'hello';
55+
public override functionHeader(
56+
{ type, args, id, returnType }: ShaderGenerator.FunctionHeaderOptions,
57+
): string {
58+
if (type === 'compute') {
59+
throw new Error('Compute shaders are not supported in GLSL');
60+
}
61+
62+
const argList = args.map((arg) => {
63+
const segment = resolveSchema(this.ctx, arg.dataType as AnyData);
64+
return `${segment.typePrefix} ${arg.value}${segment.typeSuffix}`;
65+
}).join(', ');
66+
67+
const returnSegment = resolveSchema(this.ctx, returnType);
68+
69+
if (returnSegment.typeSuffix.length > 0) {
70+
throw new Error(`Unsupported return type: ${String(returnType)}`);
71+
}
72+
73+
// Entry functions are always named 'main' in GLSL
74+
const realId = type === 'normal' ? id : 'main';
75+
76+
return `${returnSegment.typePrefix} ${realId}(${argList})`;
1277
}
1378
}
Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,51 @@
11
import { expect, test } from 'vitest';
2+
import * as d from 'typegpu/data';
23
import { asGLSL } from './utils/asGLSL.ts';
34

4-
test('functionDefinition', () => {
5+
test('no args, f32 return', () => {
56
const foo = () => {
67
'use gpu';
7-
return 1 + 2;
8+
return d.f32(1 + 2);
89
};
910

10-
expect(asGLSL(foo)).toMatchInlineSnapshot(`"fn foo() hello"`);
11+
expect(asGLSL(foo)).toMatchInlineSnapshot(`
12+
"float foo() {
13+
return 3;
14+
}"
15+
`);
16+
});
17+
18+
test('no args, void return', () => {
19+
const foo = () => {
20+
'use gpu';
21+
const a = 1 + 2;
22+
};
23+
24+
expect(asGLSL(foo)).toMatchInlineSnapshot(`
25+
"void foo() {
26+
var a = 3;
27+
}"
28+
`);
29+
});
30+
31+
test('primitive args, f32 return', () => {
32+
const foo = (a: number, b: number) => {
33+
'use gpu';
34+
return d.f32(a + b + 2);
35+
};
36+
37+
const bar = () => {
38+
'use gpu';
39+
foo(1, 2);
40+
};
41+
42+
expect(asGLSL(bar)).toMatchInlineSnapshot(`
43+
"float foo(int a, int b) {
44+
return f32(((a + b) + 2));
45+
}
46+
47+
void bar() {
48+
foo(1, 2);
49+
}"
50+
`);
1151
});

packages/typegpu/src/tgsl/shaderGenerator.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { Block, Expression, Statement } from 'tinyest';
22
import type { AnyData } from '../data/dataTypes.ts';
33
import type { Snippet } from '../data/snippet.ts';
44
import type { GenerationCtx } from './generationHelpers.ts';
5+
import type { ResolutionCtx as $ResolutionCtx } from '../types.ts';
56

67
export interface FunctionDefinitionExtra {
78
type: 'normal' | 'vertex' | 'fragment' | 'compute';
@@ -23,6 +24,7 @@ export interface ShaderGenerator {
2324
}
2425

2526
export namespace ShaderGenerator {
27+
export type ResolutionCtx = $ResolutionCtx;
2628
export interface FunctionHeaderOptions extends FunctionDefinitionExtra {
2729
id: string;
2830
args: Snippet[];

packages/typegpu/src/tgsl/wgslGenerator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ export class WgslGenerator implements ShaderGenerator {
127127
this.#ctx = ctx;
128128
}
129129

130-
private get ctx(): GenerationCtx {
130+
public get ctx(): GenerationCtx {
131131
if (!this.#ctx) {
132132
throw new Error(
133133
'WGSL Generator has not yet been initialized. Please call initialize(ctx) before using the generator.',

0 commit comments

Comments
 (0)