@@ -19,7 +19,12 @@ import { $gpuCallable, $internal, $providing, isMarkedInternal } from '../shared
1919import { safeStringify } from '../shared/stringify.ts' ;
2020import { pow } from '../std/numeric.ts' ;
2121import { 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' ;
2328import { convertStructValues , convertToCommonType , tryConvertSnippet } from './conversion.ts' ;
2429import {
2530 ArrayExpression ,
@@ -44,10 +49,15 @@ import type { ExternalMap } from '../core/resolve/externals.ts';
4449import * as forOfUtils from './forOfUtils.ts' ;
4550import { isTgpuRange } from '../std/range.ts' ;
4651import { stringifyNode } from '../shared/tseynit.ts' ;
47- import type { FunctionDefinitionOptions } from './shaderGenerator_members.ts' ;
52+ import type {
53+ ConstantDefinitionOptions ,
54+ FunctionDefinitionOptions ,
55+ VariableDefinitionOptions ,
56+ } from './shaderGenerator_members.ts' ;
4857import { getAttributesString } from '../data/attributes.ts' ;
4958import { validSelectBranchTypes } from '../std/boolean.ts' ;
5059import { isInfixDispatch } from './infixDispatch.ts' ;
60+ import type { VariableScope } from '../core/variable/tgpuVariable.ts' ;
5161
5262const { NodeTypeCatalog : NODE } = tinyest ;
5363
@@ -193,6 +203,14 @@ const binaryOpCodeToCodegen = {
193203 '**' : pow [ $gpuCallable ] . call . bind ( pow ) ,
194204} satisfies Partial < Record < tinyest . BinaryOperator , ( ...args : never [ ] ) => unknown > > ;
195205
206+ const usageToVarTemplateMap : Record < VariableScope | BindableBufferUsage , string > = {
207+ private : 'private' ,
208+ workgroup : 'workgroup' ,
209+ uniform : 'uniform' ,
210+ mutable : 'storage, read_write' ,
211+ readonly : 'storage, read' ,
212+ } ;
213+
196214export class WgslGenerator implements ShaderGenerator {
197215 #ctx: GenerationCtx | undefined = undefined ;
198216 // used to detect `continue` and `break` nodes in loop body
@@ -844,6 +862,41 @@ ${this.ctx.pre}}`;
844862 assertExhaustive ( expression ) ;
845863 }
846864
865+ public declareGlobalConst ( options : ConstantDefinitionOptions ) : ResolvedSnippet {
866+ const resolvedDataType = this . ctx . resolve ( options . dataType ) . value ;
867+ const resolvedValue = this . ctx . resolveSnippet ( options . init ) . value ;
868+
869+ this . ctx . addDeclaration ( `const ${ options . id } : ${ resolvedDataType } = ${ resolvedValue } ;` ) ;
870+
871+ return snip ( options . id , options . dataType , 'constant-immutable-def' ) ;
872+ }
873+
874+ public declareGlobalVar ( options : VariableDefinitionOptions ) : ResolvedSnippet {
875+ let pre = '' ;
876+
877+ if ( options . group !== undefined ) {
878+ pre += `@group(${ options . group } ) ` ;
879+ }
880+
881+ if ( options . binding !== undefined ) {
882+ pre += `@binding(${ options . binding } ) ` ;
883+ }
884+
885+ if ( options . scope in usageToVarTemplateMap ) {
886+ pre += `var<${ usageToVarTemplateMap [ options . scope as keyof typeof usageToVarTemplateMap ] } > ` ;
887+ } else {
888+ pre += `var ` ;
889+ }
890+
891+ pre += `${ options . id } : ${ this . ctx . resolve ( options . dataType ) . value } ` ;
892+
893+ this . ctx . addDeclaration (
894+ options . init ? `${ pre } = ${ this . ctx . resolveSnippet ( options . init ) . value } ;` : `${ pre } ;` ,
895+ ) ;
896+
897+ return snip ( options . id , options . dataType , options . scope ) ;
898+ }
899+
847900 public functionDefinition ( options : FunctionDefinitionOptions ) : string {
848901 // Function body
849902 let body = this . _block ( options . body ) ;
0 commit comments