Skip to content

Commit a523fc2

Browse files
committed
feat: Route more definitions through the shader generator
1 parent 299c9a5 commit a523fc2

6 files changed

Lines changed: 91 additions & 25 deletions

File tree

packages/typegpu/src/core/buffer/bufferUsage.ts

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,6 @@ export function isUsableAsUniform<T extends TgpuBuffer<BaseData>>(
8686
// Implementation
8787
// --------------
8888

89-
const usageToVarTemplateMap: Record<BindableBufferUsage, string> = {
90-
uniform: 'uniform',
91-
mutable: 'storage, read_write',
92-
readonly: 'storage, read',
93-
};
94-
9589
class TgpuFixedBufferImpl<TData extends BaseData, TUsage extends BindableBufferUsage>
9690
implements TgpuBufferUsage<TData, TUsage>, SelfResolvable, TgpuFixedBufferUsage<TData>
9791
{
@@ -123,10 +117,16 @@ class TgpuFixedBufferImpl<TData extends BaseData, TUsage extends BindableBufferU
123117
this.usage === 'uniform' ? { uniform: dataType } : { storage: dataType, access: this.usage },
124118
this.buffer,
125119
);
126-
const usage = usageToVarTemplateMap[this.usage];
127120

128121
ctx.addDeclaration(
129-
`@group(${group}) @binding(${binding}) var<${usage}> ${id}: ${ctx.resolve(dataType).value};`,
122+
ctx.gen.globalVarDefinition({
123+
scope: this.usage,
124+
name: id,
125+
dataType,
126+
group: group,
127+
binding: binding,
128+
init: undefined,
129+
}),
130130
);
131131

132132
return snip(id, dataType, this.usage);
@@ -243,12 +243,16 @@ export class TgpuLaidOutBufferImpl<TData extends BaseData, TUsage extends Bindab
243243
[$resolve](ctx: ResolutionCtx): ResolvedSnippet {
244244
const id = ctx.makeUniqueIdentifier(getName(this), 'global');
245245
const group = ctx.allocateLayoutEntry(this.#membership.layout);
246-
const usage = usageToVarTemplateMap[this.usage];
247246

248247
ctx.addDeclaration(
249-
`@group(${group}) @binding(${this.#membership.idx}) var<${usage}> ${id}: ${
250-
ctx.resolve(this.dataType).value
251-
};`,
248+
ctx.gen.globalVarDefinition({
249+
scope: this.usage,
250+
name: id,
251+
dataType: this.dataType,
252+
group: group,
253+
binding: this.#membership.idx,
254+
init: undefined,
255+
}),
252256
);
253257

254258
return snip(id, this.dataType, this.usage);

packages/typegpu/src/core/constant/tgpuConstant.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,14 @@ class TgpuConstImpl<TDataType extends BaseData> implements TgpuConst<TDataType>,
109109

110110
[$resolve](ctx: ResolutionCtx): ResolvedSnippet {
111111
const id = ctx.makeUniqueIdentifier(getName(this), 'global');
112-
const resolvedDataType = ctx.resolve(this.dataType).value;
113-
const resolvedValue = ctx.resolve(this.#value, this.dataType).value;
114112

115-
ctx.addDeclaration(`const ${id}: ${resolvedDataType} = ${resolvedValue};`);
113+
ctx.addDeclaration(
114+
ctx.gen.globalConstDefinition(
115+
id,
116+
this.dataType,
117+
snip(this.#value, this.dataType, 'constant'),
118+
),
119+
);
116120

117121
return snip(id, this.dataType, 'constant-immutable-def');
118122
}

packages/typegpu/src/core/variable/tgpuVariable.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,13 @@ class TgpuVarImpl<TScope extends VariableScope, TDataType extends BaseData>
8888

8989
[$resolve](ctx: ResolutionCtx): ResolvedSnippet {
9090
const id = ctx.makeUniqueIdentifier(getName(this), 'global');
91-
const pre = `var<${this.#scope}> ${id}: ${ctx.resolve(this.#dataType).value}`;
91+
const init = this.#initialValue
92+
? snip(this.#initialValue, this.#dataType, 'constant')
93+
: undefined;
9294

93-
if (this.#initialValue) {
94-
ctx.addDeclaration(`${pre} = ${ctx.resolve(this.#initialValue, this.#dataType).value};`);
95-
} else {
96-
ctx.addDeclaration(`${pre};`);
97-
}
95+
ctx.addDeclaration(
96+
ctx.gen.globalVarDefinition({ scope: this.#scope, name: id, dataType: this.#dataType, init }),
97+
);
9898

9999
return snip(id, this.#dataType, this.#scope);
100100
}

packages/typegpu/src/tgsl/shaderGenerator.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import type { BaseData } from '../data/wgslTypes.ts';
22
import type { GenerationCtx } from './generationHelpers.ts';
33
import type { ResolvedSnippet, Snippet } from '../data/snippet.ts';
4-
import type { FunctionDefinitionOptions } from './shaderGenerator_members.ts';
4+
import type {
5+
FunctionDefinitionOptions,
6+
VariableDefinitionOptions,
7+
} from './shaderGenerator_members.ts';
58

69
/**
710
* **NOTE: This is an unstable API and may change in the future.**
@@ -12,7 +15,10 @@ import type { FunctionDefinitionOptions } from './shaderGenerator_members.ts';
1215
export interface ShaderGenerator {
1316
initGenerator(ctx: GenerationCtx): void;
1417

18+
globalConstDefinition(id: string, schema: BaseData, init: Snippet): string;
19+
globalVarDefinition(options: VariableDefinitionOptions): string;
1520
functionDefinition(options: FunctionDefinitionOptions): string;
21+
1622
typeInstantiation(schema: BaseData, args: readonly Snippet[]): ResolvedSnippet;
1723
typeAnnotation(schema: BaseData): string;
1824
}

packages/typegpu/src/tgsl/shaderGenerator_members.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import type { Block } from 'tinyest';
22
import type { BaseData } from '../data/wgslTypes.ts';
3-
import type { FunctionArgument, TgpuShaderStage } from '../types.ts';
3+
import type { BindableBufferUsage, FunctionArgument, TgpuShaderStage } from '../types.ts';
4+
import type { VariableScope } from '../core/variable/tgpuVariable.ts';
5+
import type { Snippet } from '../data/snippet.ts';
46

57
export { UnknownData } from '../data/dataTypes.ts';
68
export { getName } from '../shared/meta.ts';
@@ -19,3 +21,12 @@ export interface FunctionDefinitionOptions {
1921

2022
determineReturnType(): BaseData;
2123
}
24+
25+
export interface VariableDefinitionOptions {
26+
readonly scope: VariableScope | BindableBufferUsage;
27+
readonly name: string;
28+
readonly dataType: BaseData;
29+
readonly init: Snippet | undefined;
30+
readonly group?: string | undefined;
31+
readonly binding?: number | undefined;
32+
}

packages/typegpu/src/tgsl/wgslGenerator.ts

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,12 @@ import { $gpuCallable, $internal, $providing, isMarkedInternal } from '../shared
1919
import { safeStringify } from '../shared/stringify.ts';
2020
import { pow } from '../std/numeric.ts';
2121
import { add, div, mul, neg, sub } from '../std/operators.ts';
22-
import { isGPUCallable, isKnownAtComptime, type DualFn } from '../types.ts';
22+
import {
23+
isGPUCallable,
24+
isKnownAtComptime,
25+
type BindableBufferUsage,
26+
type DualFn,
27+
} from '../types.ts';
2328
import { convertStructValues, convertToCommonType, tryConvertSnippet } from './conversion.ts';
2429
import {
2530
ArrayExpression,
@@ -44,10 +49,14 @@ import type { ExternalMap } from '../core/resolve/externals.ts';
4449
import * as forOfUtils from './forOfUtils.ts';
4550
import { isTgpuRange } from '../std/range.ts';
4651
import { stringifyNode } from '../shared/tseynit.ts';
47-
import type { FunctionDefinitionOptions } from './shaderGenerator_members.ts';
52+
import type {
53+
FunctionDefinitionOptions,
54+
VariableDefinitionOptions,
55+
} from './shaderGenerator_members.ts';
4856
import { getAttributesString } from '../data/attributes.ts';
4957
import { validSelectBranchTypes } from '../std/boolean.ts';
5058
import { isInfixDispatch } from './infixDispatch.ts';
59+
import type { VariableScope } from '../core/variable/tgpuVariable.ts';
5160

5261
const { NodeTypeCatalog: NODE } = tinyest;
5362

@@ -193,6 +202,14 @@ const binaryOpCodeToCodegen = {
193202
'**': pow[$gpuCallable].call.bind(pow),
194203
} satisfies Partial<Record<tinyest.BinaryOperator, (...args: never[]) => unknown>>;
195204

205+
const usageToVarTemplateMap: Record<VariableScope | BindableBufferUsage, string> = {
206+
private: 'private',
207+
workgroup: 'workgroup',
208+
uniform: 'uniform',
209+
mutable: 'storage, read_write',
210+
readonly: 'storage, read',
211+
};
212+
196213
export class WgslGenerator implements ShaderGenerator {
197214
#ctx: GenerationCtx | undefined = undefined;
198215
// used to detect `continue` and `break` nodes in loop body
@@ -844,6 +861,30 @@ ${this.ctx.pre}}`;
844861
assertExhaustive(expression);
845862
}
846863

864+
public globalConstDefinition(id: string, schema: wgsl.BaseData, init: Snippet): string {
865+
const resolvedDataType = this.ctx.resolve(schema).value;
866+
const resolvedValue = this.ctx.resolveSnippet(init).value;
867+
868+
return `const ${id}: ${resolvedDataType} = ${resolvedValue};`;
869+
}
870+
871+
public globalVarDefinition(options: VariableDefinitionOptions): string {
872+
let pre = `var<${usageToVarTemplateMap[options.scope]}> ${options.name}: ${this.ctx.resolve(options.dataType).value}`;
873+
874+
if (options.binding !== undefined) {
875+
pre = `@binding(${options.binding}) ` + pre;
876+
}
877+
878+
if (options.group !== undefined) {
879+
pre = `@group(${options.group}) ` + pre;
880+
}
881+
882+
if (options.init) {
883+
return `${pre} = ${this.ctx.resolveSnippet(options.init).value};`;
884+
}
885+
return `${pre};`;
886+
}
887+
847888
public functionDefinition(options: FunctionDefinitionOptions): string {
848889
// Function body
849890
let body = this._block(options.body);

0 commit comments

Comments
 (0)