@@ -11,6 +11,7 @@ interface VinculumModule {
1111
1212interface VinculumSpec {
1313 version : string ;
14+ engine : string ;
1415 channels : string [ ] ;
1516 modules : Record < string , VinculumModule > ;
1617 compiler : {
@@ -35,9 +36,10 @@ export class VinculumCompiler {
3536 this . dag . set ( name , new Set ( mod . requires || [ ] ) ) ;
3637 // Auto-inject conservation if flux_producer writes water/sand
3738 if ( mod . flux_producer && ( mod . writes . includes ( 'water' ) || mod . writes . includes ( 'sand' ) ) ) {
38- if ( ! mod . requires ?. includes ( 'semi_implicit_conservation' ) ) {
39- mod . requires = [ ...( mod . requires || [ ] ) , 'semi_implicit_conservation' ] ;
40- this . dag . set ( name , new Set ( mod . requires ) ) ;
39+ const consMod = this . spec . modules [ 'semi_implicit_conservation' ] ;
40+ if ( consMod && ! consMod . requires ?. includes ( name ) ) {
41+ consMod . requires = [ ...( consMod . requires || [ ] ) , name ] ;
42+ this . dag . set ( 'semi_implicit_conservation' , new Set ( consMod . requires ) ) ;
4143 }
4244 }
4345 }
@@ -93,18 +95,36 @@ export class VinculumCompiler {
9395
9496 // Generate WebGPU dispatch sequence
9597 let code = `// Auto-generated by Vinculum Compiler v${ this . spec . version } \n` ;
96- code += `const dispatchSequence = [\n` ;
98+ code += `// Pipeline: ${ this . spec . engine } \n\n` ;
99+ code += `export const dispatchSequence = [\n` ;
100+
101+ let currentState = 'state_A' ;
97102
98103 for ( const modName of order ) {
99104 const mod = this . spec . modules [ modName ] ;
100- code += ` { name: '${ modName } ', shader: '${ mod . shader } ', binds: this.setupBindGroup('${ modName } ') },\n` ;
105+ const mutatesState = mod . writes && mod . writes . length > 0 ;
106+
107+ let inputBuffer = currentState ;
108+ let outputBuffer = currentState ;
109+
110+ if ( mutatesState ) {
111+ outputBuffer = currentState === 'state_A' ? 'state_B' : 'state_A' ;
112+ currentState = outputBuffer ; // state flips for next read
113+ }
114+
115+ code += ` {\n` ;
116+ code += ` name: '${ modName } ',\n` ;
117+ code += ` shader: '${ mod . shader } ',\n` ;
118+ code += ` bufferRoles: { input: '${ inputBuffer } ', output: '${ outputBuffer } ' },\n` ;
119+ code += ` binds: () => setupBindGroup('${ modName } ')\n` ;
120+ code += ` },\n` ;
101121 }
102- code += `];\n` ;
122+ code += `];\n\n ` ;
103123
104124 // Inject adaptive substep hint if high-flux modules present
105- if ( this . spec . compiler . injection . substep_hint === 'high-flux' ) {
125+ if ( this . spec . compiler ? .injection ? .substep_hint === 'high-flux' ) {
106126 code += `// Hint: enable adaptive substepping for high-flux modules\n` ;
107- code += `simulationParams.substepThreshold = 0.05;\n` ;
127+ code += `export const recommendedSubstepThreshold = 0.05;\n` ;
108128 }
109129
110130 return code ;
@@ -116,24 +136,35 @@ export class VinculumCompiler {
116136 const result : string [ ] = [ ] ;
117137 const queue : string [ ] = [ ] ;
118138
139+ console . log ( "DAG contents:" ) ;
140+ for ( const [ mod , deps ] of this . dag . entries ( ) ) {
141+ console . log ( `${ mod } requires:` , Array . from ( deps ) ) ;
142+ }
143+
119144 // Initialize in-degrees
120145 for ( const mod of Object . keys ( this . spec . modules ) ) {
121146 inDegree . set ( mod , 0 ) ;
122147 }
123- for ( const deps of this . dag . values ( ) ) {
148+ // If mod requires dep, edge is dep -> mod.
149+ // So mod's inDegree increases.
150+ for ( const [ mod , deps ] of this . dag ) {
124151 for ( const dep of deps ) {
125- inDegree . set ( dep , ( inDegree . get ( dep ) || 0 ) + 1 ) ;
152+ // If a required dependency isn't in modules, skip or initialize
153+ if ( inDegree . has ( dep ) ) {
154+ inDegree . set ( mod , ( inDegree . get ( mod ) || 0 ) + 1 ) ;
155+ }
126156 }
127157 }
128158
129- // Start with nodes that have no dependencies
159+ // Start with nodes that have no dependencies (inDegree = 0)
130160 for ( const [ mod , deg ] of inDegree ) {
131161 if ( deg === 0 ) queue . push ( mod ) ;
132162 }
133163
134164 while ( queue . length ) {
135165 const curr = queue . shift ( ) ! ;
136166 result . push ( curr ) ;
167+ // curr just executed. Find any mod that requires curr, and decrement its inDegree.
137168 for ( const [ mod , deps ] of this . dag ) {
138169 if ( deps . has ( curr ) ) {
139170 inDegree . set ( mod , inDegree . get ( mod ) ! - 1 ) ;
0 commit comments