-
-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Expand file tree
/
Copy pathstrands_codegen.js
More file actions
106 lines (93 loc) · 3.69 KB
/
strands_codegen.js
File metadata and controls
106 lines (93 loc) · 3.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import { sortCFG } from './ir_cfg';
import * as DAG from './ir_dag';
import { NodeType, StatementType, structType, TypeInfoFromGLSLName } from './ir_types';
export function generateShaderCode(strandsContext) {
const {
cfg,
backend,
vertexDeclarations,
fragmentDeclarations,
computeDeclarations
} = strandsContext;
const hooksObj = {
uniforms: {},
storageUniforms: {},
varyingVariables: [],
};
for (const {name, typeInfo, defaultValue} of strandsContext.uniforms) {
if (typeInfo.baseType === 'storage') {
if (defaultValue !== null && defaultValue !== undefined) {
hooksObj.storageUniforms[name] = defaultValue;
}
} else {
const key = backend.generateHookUniformKey(name, typeInfo);
if (key !== null) {
hooksObj.uniforms[key] = defaultValue;
}
}
}
// Add texture bindings to declarations for WebGPU backend
if (backend.addTextureBindingsToDeclarations) {
backend.addTextureBindingsToDeclarations(strandsContext);
}
// Add storage buffer bindings to declarations for WebGPU backend
if (backend.addStorageBufferBindingsToDeclarations) {
backend.addStorageBufferBindingsToDeclarations(strandsContext);
}
for (const { hookType, rootNodeID, entryBlockID, shaderContext } of strandsContext.hooks) {
const generationContext = {
indent: 1,
codeLines: [],
write(line) {
this.codeLines.push(' '.repeat(this.indent) + line);
},
tempNames: {},
declarations: [],
nextTempID: 0,
visitedNodes: new Set(),
shaderContext, // 'vertex' or 'fragment'
strandsContext, // For shared variable tracking
};
const blocks = sortCFG(cfg.outgoingEdges, entryBlockID);
for (const blockID of blocks) {
backend.generateBlock(blockID, strandsContext, generationContext);
}
const firstLine = backend.hookEntry(hookType);
let returnType;
if (hookType.returnType.properties) {
returnType = structType(hookType.returnType);
} else if (!hookType.returnType.dataType || hookType.returnType.typeName?.trim() === 'void') {
returnType = null;
} else {
returnType = hookType.returnType.dataType;
}
if (rootNodeID !== undefined) {
backend.generateReturnStatement(strandsContext, generationContext, rootNodeID, returnType);
}
hooksObj[`${hookType.returnType.typeName} ${hookType.name}`] = [firstLine, ...generationContext.codeLines, '}'].join('\n');
}
// Finalize shared variable declarations based on usage
if (strandsContext.sharedVariables) {
for (const [varName, varInfo] of strandsContext.sharedVariables) {
if (varInfo.usedInVertex && varInfo.usedInFragment) {
// Used in both shaders - this is a true varying variable
hooksObj.varyingVariables.push(backend.generateVaryingVariable(varName, varInfo.typeInfo));
} else if (varInfo.usedInVertex) {
// Only used in vertex shader - declare as local variable
vertexDeclarations.add(backend.generateLocalDeclaration(varName, varInfo.typeInfo));
} else if (varInfo.usedInFragment) {
// Only used in fragment shader - declare as local variable
fragmentDeclarations.add(backend.generateLocalDeclaration(varName, varInfo.typeInfo));
}
// If not used anywhere, don't declare it
}
}
// Register instanceID varying if used in a fragment hook
if (strandsContext._instanceIDUsedInFragment) {
hooksObj.instanceIDVarying = backend.generateInstanceIDVarying();
}
hooksObj.vertexDeclarations = [...vertexDeclarations].join('\n');
hooksObj.fragmentDeclarations = [...fragmentDeclarations].join('\n');
hooksObj.computeDeclarations = [...computeDeclarations].join('\n');
return hooksObj;
}