forked from gpujs/gpu.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfunction-node.js
More file actions
190 lines (172 loc) · 4.54 KB
/
function-node.js
File metadata and controls
190 lines (172 loc) · 4.54 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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
'use strict';
const WebGLFunctionNode = require('../web-gl/function-node');
// Closure capture for the ast function, prevent collision with existing AST functions
// The prefixes to use
const constantsPrefix = 'this.constants.';
const DECODE32_ENCODE32 = /decode32\(\s+encode32\(/g;
const ENCODE32_DECODE32 = /encode32\(\s+decode32\(/g;
/**
* @class WebGL2FunctionNode
*
* @desc [INTERNAL] Takes in a function node, and does all the AST voodoo required to generate its respective webGL code.
*
* @extends WebGLFunctionNode
*
* @returns the converted webGL function string
*
*/
module.exports = class WebGL2FunctionNode extends WebGLFunctionNode {
generate() {
if (this.debug) {
console.log(this);
}
if (this.prototypeOnly) {
return WebGL2FunctionNode.astFunctionPrototype(this.getJsAST(), [], this).join('').trim();
} else {
this.functionStringArray = this.astGeneric(this.getJsAST(), [], this);
}
this.functionString = webGlRegexOptimize(
this.functionStringArray.join('').trim()
);
return this.functionString;
}
/**
* @memberOf WebGL2FunctionNode#
* @function
* @name astFunctionExpression
*
* @desc Parses the abstract syntax tree for to its *named function*
*
* @param {Object} ast - the AST object to parse
* @param {Array} retArr - return array string
*
* @returns {Array} the append retArr
*/
astFunctionExpression(ast, retArr) {
// Setup function return type and name
if (this.isRootKernel) {
retArr.push('void');
this.kernalAst = ast;
} else {
retArr.push(this.returnType);
}
retArr.push(' ');
retArr.push(this.functionName);
retArr.push('(');
if (!this.isRootKernel) {
// Arguments handling
for (let i = 0; i < this.paramNames.length; ++i) {
const paramName = this.paramNames[i];
if (i > 0) {
retArr.push(', ');
}
const type = this.getParamType(paramName);
switch (type) {
case 'Texture':
case 'Input':
case 'Array':
case 'HTMLImage':
retArr.push('sampler2D');
break;
default:
retArr.push('float');
}
retArr.push(' ');
retArr.push('user_');
retArr.push(paramName);
}
}
// Function opening
retArr.push(') {\n');
// Body statement iteration
for (let i = 0; i < ast.body.body.length; ++i) {
this.astGeneric(ast.body.body[i], retArr);
retArr.push('\n');
}
// Function closing
retArr.push('}\n');
return retArr;
}
/**
* @memberOf WebGL2FunctionNode#
* @function
* @name astIdentifierExpression
*
* @desc Parses the abstract syntax tree for *identifier* expression
*
* @param {Object} idtNode - An ast Node
* @param {Array} retArr - return array string
*
* @returns {Array} the append retArr
*/
astIdentifierExpression(idtNode, retArr) {
if (idtNode.type !== 'Identifier') {
throw this.astErrorOutput(
'IdentifierExpression - not an Identifier',
idtNode
);
}
// do we need to cast addressing vales to float?
const castFloat = !this.isState('in-get-call-parameters');
switch (idtNode.name) {
case 'gpu_threadX':
castFloat && retArr.push('float(');
retArr.push('threadId.x');
castFloat && retArr.push(')');
break;
case 'gpu_threadY':
castFloat && retArr.push('float(');
retArr.push('threadId.y');
castFloat && retArr.push(')');
break;
case 'gpu_threadZ':
castFloat && retArr.push('float(');
retArr.push('threadId.z');
castFloat && retArr.push(')');
break;
case 'gpu_outputX':
retArr.push('uOutputDim.x');
break;
case 'gpu_outputY':
retArr.push('uOutputDim.y');
break;
case 'gpu_outputZ':
retArr.push('uOutputDim.z');
break;
case 'Infinity':
retArr.push('intBitsToFloat(2139095039)');
break;
default:
if (this.constants && this.constants.hasOwnProperty(idtNode.name)) {
this.pushParameter(retArr, 'constants_' + idtNode.name);
} else {
const userParamName = this.getUserParamName(idtNode.name);
if (userParamName !== null) {
this.pushParameter(retArr, 'user_' + userParamName);
} else {
this.pushParameter(retArr, 'user_' + idtNode.name);
}
}
}
return retArr;
}
};
/**
* @ignore
* @function
* @name webgl_regex_optimize
*
* @desc [INTERNAL] Takes the near final webgl function string, and do regex search and replacments.
* For voodoo optimize out the following:
*
* - decode32(encode32( <br>
* - encode32(decode32( <br>
*
* @param {String} inStr - The webGl function String
*
*/
function webGlRegexOptimize(inStr) {
return inStr
.replace(DECODE32_ENCODE32, '((')
.replace(ENCODE32_DECODE32, '((');
}