glre 0.36.0 → 0.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +28 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +186 -152
- package/dist/index.js +28 -26
- package/dist/index.js.map +1 -1
- package/dist/native.cjs +28 -26
- package/dist/native.cjs.map +1 -1
- package/dist/native.d.ts +2 -1
- package/dist/native.js +28 -26
- package/dist/native.js.map +1 -1
- package/dist/react.cjs +28 -26
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +28 -26
- package/dist/react.js.map +1 -1
- package/dist/solid.cjs +28 -26
- package/dist/solid.cjs.map +1 -1
- package/dist/solid.d.ts +1 -1
- package/dist/solid.js +28 -26
- package/dist/solid.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +2 -0
- package/src/node/core.ts +25 -4
- package/src/node/index.ts +61 -64
- package/src/node/node.ts +6 -3
- package/src/node/scope.ts +3 -2
- package/src/node/types.ts +142 -121
- package/src/node/utils/const.ts +111 -119
- package/src/node/utils/index.ts +19 -5
- package/src/node/utils/infer.ts +6 -11
- package/src/node/utils/parse.ts +49 -5
- package/src/node/utils/utils.ts +9 -2
- package/src/types.ts +2 -0
- package/src/utils/program.ts +61 -17
- package/src/webgl.ts +79 -67
- package/src/webgpu.ts +50 -42
package/src/node/utils/const.ts
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
export const SWIZZLES = ['x', 'y', 'z', 'w', 'r', 'g', 'b', 'a', 's', 't', 'p', 'q'] as const
|
|
2
2
|
|
|
3
|
+
// Unified order with TYPE_MAPPING array
|
|
4
|
+
export const CONVERSIONS = [
|
|
5
|
+
'toBool',
|
|
6
|
+
'toUint',
|
|
7
|
+
'toInt',
|
|
8
|
+
'toFloat',
|
|
9
|
+
'toBvec2',
|
|
10
|
+
'toIvec2',
|
|
11
|
+
'toUvec2',
|
|
12
|
+
'toVec2',
|
|
13
|
+
'toBvec3',
|
|
14
|
+
'toIvec3',
|
|
15
|
+
'toUvec3',
|
|
16
|
+
'toVec3',
|
|
17
|
+
'toBvec4',
|
|
18
|
+
'toIvec4',
|
|
19
|
+
'toUvec4',
|
|
20
|
+
'toVec4',
|
|
21
|
+
'toColor',
|
|
22
|
+
'toMat2',
|
|
23
|
+
'toMat3',
|
|
24
|
+
'toMat4',
|
|
25
|
+
] as const
|
|
26
|
+
|
|
27
|
+
// Unified order with CONVERSIONS array
|
|
3
28
|
export const TYPE_MAPPING = {
|
|
4
29
|
bool: 'bool',
|
|
5
30
|
uint: 'u32',
|
|
@@ -28,29 +53,6 @@ export const TYPE_MAPPING = {
|
|
|
28
53
|
|
|
29
54
|
export const CONSTANTS = Object.keys(TYPE_MAPPING) as unknown as keyof typeof TYPE_MAPPING
|
|
30
55
|
|
|
31
|
-
export const CONVERSIONS = [
|
|
32
|
-
'toBool',
|
|
33
|
-
'toUint',
|
|
34
|
-
'toInt',
|
|
35
|
-
'toFloat',
|
|
36
|
-
'toBvec2',
|
|
37
|
-
'toIvec2',
|
|
38
|
-
'toUvec2',
|
|
39
|
-
'toVec2',
|
|
40
|
-
'toBvec3',
|
|
41
|
-
'toIvec3',
|
|
42
|
-
'toUvec3',
|
|
43
|
-
'toVec3',
|
|
44
|
-
'toBvec4',
|
|
45
|
-
'toIvec4',
|
|
46
|
-
'toUvec4',
|
|
47
|
-
'toVec4',
|
|
48
|
-
'toColor',
|
|
49
|
-
'toMat2',
|
|
50
|
-
'toMat3',
|
|
51
|
-
'toMat4',
|
|
52
|
-
] as const
|
|
53
|
-
|
|
54
56
|
export const OPERATORS = {
|
|
55
57
|
add: '+',
|
|
56
58
|
sub: '-',
|
|
@@ -74,84 +76,6 @@ export const OPERATORS = {
|
|
|
74
76
|
|
|
75
77
|
export const OPERATOR_KEYS = Object.keys(OPERATORS) as (keyof typeof OPERATORS)[]
|
|
76
78
|
|
|
77
|
-
// All shader functions (type inference now handled by inferFrom)
|
|
78
|
-
export const FUNCTIONS = [
|
|
79
|
-
// Float return functions
|
|
80
|
-
'dot',
|
|
81
|
-
'distance',
|
|
82
|
-
'length',
|
|
83
|
-
'lengthSq',
|
|
84
|
-
'determinant',
|
|
85
|
-
'luminance',
|
|
86
|
-
// Bool return functions
|
|
87
|
-
'all',
|
|
88
|
-
'any',
|
|
89
|
-
// Component-wise functions (preserve input type)
|
|
90
|
-
'abs',
|
|
91
|
-
'sign',
|
|
92
|
-
'floor',
|
|
93
|
-
'ceil',
|
|
94
|
-
'round',
|
|
95
|
-
'fract',
|
|
96
|
-
'trunc',
|
|
97
|
-
'sin',
|
|
98
|
-
'cos',
|
|
99
|
-
'tan',
|
|
100
|
-
'asin',
|
|
101
|
-
'acos',
|
|
102
|
-
'atan',
|
|
103
|
-
'sinh',
|
|
104
|
-
'cosh',
|
|
105
|
-
'tanh',
|
|
106
|
-
'asinh',
|
|
107
|
-
'acosh',
|
|
108
|
-
'atanh',
|
|
109
|
-
'exp',
|
|
110
|
-
'exp2',
|
|
111
|
-
'log',
|
|
112
|
-
'log2',
|
|
113
|
-
'sqrt',
|
|
114
|
-
'inverseSqrt',
|
|
115
|
-
'normalize',
|
|
116
|
-
'oneMinus',
|
|
117
|
-
'saturate',
|
|
118
|
-
'negate',
|
|
119
|
-
'reciprocal',
|
|
120
|
-
'dFdx',
|
|
121
|
-
'dFdy',
|
|
122
|
-
'fwidth',
|
|
123
|
-
'degrees',
|
|
124
|
-
'radians',
|
|
125
|
-
// Vector functions
|
|
126
|
-
'cross',
|
|
127
|
-
'reflect',
|
|
128
|
-
'refract',
|
|
129
|
-
// Multi-argument functions
|
|
130
|
-
'min',
|
|
131
|
-
'max',
|
|
132
|
-
'mix',
|
|
133
|
-
'clamp',
|
|
134
|
-
'step',
|
|
135
|
-
'smoothstep',
|
|
136
|
-
'pow',
|
|
137
|
-
'atan2',
|
|
138
|
-
// Texture functions
|
|
139
|
-
'texture',
|
|
140
|
-
'textureLod',
|
|
141
|
-
'textureSize',
|
|
142
|
-
'cubeTexture',
|
|
143
|
-
// Utility functions
|
|
144
|
-
'faceforward',
|
|
145
|
-
'bitcast',
|
|
146
|
-
'cbrt',
|
|
147
|
-
'difference',
|
|
148
|
-
'equals',
|
|
149
|
-
'pow2',
|
|
150
|
-
'pow3',
|
|
151
|
-
'pow4',
|
|
152
|
-
'transformDirection',
|
|
153
|
-
] as const
|
|
154
|
-
|
|
155
79
|
export const COMPONENT_COUNT_TO_TYPE = {
|
|
156
80
|
1: 'float',
|
|
157
81
|
2: 'vec2',
|
|
@@ -161,24 +85,6 @@ export const COMPONENT_COUNT_TO_TYPE = {
|
|
|
161
85
|
16: 'mat4',
|
|
162
86
|
} as const
|
|
163
87
|
|
|
164
|
-
// Function return type mapping for method chaining
|
|
165
|
-
export const FUNCTION_RETURN_TYPES = {
|
|
166
|
-
// Always return vec4
|
|
167
|
-
texture: 'vec4',
|
|
168
|
-
cubeTexture: 'vec4',
|
|
169
|
-
textureSize: 'vec4',
|
|
170
|
-
// Always return float
|
|
171
|
-
length: 'float',
|
|
172
|
-
lengthSq: 'float',
|
|
173
|
-
distance: 'float',
|
|
174
|
-
dot: 'float',
|
|
175
|
-
// Always return bool
|
|
176
|
-
all: 'bool',
|
|
177
|
-
any: 'bool',
|
|
178
|
-
// Always return vec3
|
|
179
|
-
cross: 'vec3',
|
|
180
|
-
} as const
|
|
181
|
-
|
|
182
88
|
export const BUILTIN_TYPES = {
|
|
183
89
|
// WGSL builtin variables
|
|
184
90
|
position: 'vec4',
|
|
@@ -189,6 +95,7 @@ export const BUILTIN_TYPES = {
|
|
|
189
95
|
sample_index: 'uint',
|
|
190
96
|
sample_mask: 'uint',
|
|
191
97
|
point_coord: 'vec2',
|
|
98
|
+
global_invocation_id: 'uvec3',
|
|
192
99
|
|
|
193
100
|
// TSL compatible variables
|
|
194
101
|
positionLocal: 'vec3',
|
|
@@ -238,3 +145,88 @@ export const WGSL_TO_GLSL_BUILTIN = {
|
|
|
238
145
|
point_coord: 'gl_PointCoord',
|
|
239
146
|
uv: 'gl_FragCoord.xy',
|
|
240
147
|
} as const
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* 2.1. unified with:
|
|
151
|
+
* 1.1. index.ts functions and
|
|
152
|
+
* 3.1. types.ts BaseNodeProxy
|
|
153
|
+
*/
|
|
154
|
+
// Function return type mapping for method chaining
|
|
155
|
+
export const FUNCTION_RETURN_TYPES = {
|
|
156
|
+
// 0. Always return bool
|
|
157
|
+
all: 'bool',
|
|
158
|
+
any: 'bool',
|
|
159
|
+
// 2. Always return float
|
|
160
|
+
determinant: 'float',
|
|
161
|
+
distance: 'float',
|
|
162
|
+
dot: 'float',
|
|
163
|
+
length: 'float',
|
|
164
|
+
lengthSq: 'float',
|
|
165
|
+
luminance: 'float',
|
|
166
|
+
// 3. Always return vec3
|
|
167
|
+
cross: 'vec3',
|
|
168
|
+
// 4. Always return vec4
|
|
169
|
+
cubeTexture: 'vec4',
|
|
170
|
+
texture: 'vec4',
|
|
171
|
+
texelFetch: 'vec4',
|
|
172
|
+
textureLod: 'vec4',
|
|
173
|
+
} as const
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* 2.2. unified with:
|
|
177
|
+
* 1.2. index.ts functions and
|
|
178
|
+
* 3.2. types.ts BaseNodeProxy
|
|
179
|
+
*/
|
|
180
|
+
// All shader functions (type inference now handled by inferFrom)
|
|
181
|
+
export const FUNCTIONS = [
|
|
182
|
+
...(Object.keys(FUNCTION_RETURN_TYPES) as (keyof typeof FUNCTION_RETURN_TYPES)[]),
|
|
183
|
+
// 0. Component-wise functions
|
|
184
|
+
'abs',
|
|
185
|
+
'acos',
|
|
186
|
+
'acosh',
|
|
187
|
+
'asin',
|
|
188
|
+
'asinh',
|
|
189
|
+
'atan',
|
|
190
|
+
'atanh',
|
|
191
|
+
'ceil',
|
|
192
|
+
'cos',
|
|
193
|
+
'cosh',
|
|
194
|
+
'dFdx',
|
|
195
|
+
'dFdy',
|
|
196
|
+
'degrees',
|
|
197
|
+
'exp',
|
|
198
|
+
'exp2',
|
|
199
|
+
'floor',
|
|
200
|
+
'fract',
|
|
201
|
+
'fwidth',
|
|
202
|
+
'inverseSqrt',
|
|
203
|
+
'log',
|
|
204
|
+
'log2',
|
|
205
|
+
'negate',
|
|
206
|
+
'normalize',
|
|
207
|
+
'oneMinus',
|
|
208
|
+
'radians',
|
|
209
|
+
'reciprocal',
|
|
210
|
+
'round',
|
|
211
|
+
'saturate',
|
|
212
|
+
'sign',
|
|
213
|
+
'sin',
|
|
214
|
+
'sinh',
|
|
215
|
+
'sqrt',
|
|
216
|
+
'tan',
|
|
217
|
+
'tanh',
|
|
218
|
+
'trunc',
|
|
219
|
+
// 1. Functions where first argument determines return type
|
|
220
|
+
'atan2',
|
|
221
|
+
'clamp',
|
|
222
|
+
'max',
|
|
223
|
+
'min',
|
|
224
|
+
'mix',
|
|
225
|
+
'pow',
|
|
226
|
+
'reflect',
|
|
227
|
+
'refract',
|
|
228
|
+
// 2. Functions where not first argument determines return type
|
|
229
|
+
'smoothstep',
|
|
230
|
+
'step',
|
|
231
|
+
// @NOTE: mod is operator
|
|
232
|
+
] as const
|
package/src/node/utils/index.ts
CHANGED
|
@@ -5,13 +5,16 @@ import {
|
|
|
5
5
|
parseConstantHead,
|
|
6
6
|
parseDeclare,
|
|
7
7
|
parseDefine,
|
|
8
|
+
parseGather,
|
|
8
9
|
parseIf,
|
|
10
|
+
parseScatter,
|
|
11
|
+
parseStorageHead,
|
|
9
12
|
parseStruct,
|
|
10
13
|
parseStructHead,
|
|
11
14
|
parseSwitch,
|
|
12
15
|
parseTexture,
|
|
13
|
-
parseVaryingHead,
|
|
14
16
|
parseUniformHead,
|
|
17
|
+
parseVaryingHead,
|
|
15
18
|
} from './parse'
|
|
16
19
|
import { getBluiltin, getOperator, getConversions, safeEventCall, getEventFun, initNodeContext } from './utils'
|
|
17
20
|
import { is } from '../../utils/helpers'
|
|
@@ -42,6 +45,16 @@ export const code = <T extends Constants>(target: X<T>, c?: NodeContext | null):
|
|
|
42
45
|
if (type === 'variable') return id
|
|
43
46
|
if (type === 'member') return `${code(x, c)}.${code(y, c)}`
|
|
44
47
|
if (type === 'element') return `${code(x, c)}[${code(y, c)}]`
|
|
48
|
+
if (type === 'gather')
|
|
49
|
+
return c.isWebGL //
|
|
50
|
+
? parseGather(c, x, y, target)
|
|
51
|
+
: `${code(x, c)}[${code(y, c)}]`
|
|
52
|
+
if (type === 'scatter') {
|
|
53
|
+
const [storageNode, indexNode] = x.props.children ?? [] // x is gather node
|
|
54
|
+
return c.isWebGL
|
|
55
|
+
? parseScatter(c, storageNode, y) // indexNode is not using
|
|
56
|
+
: `${code(storageNode, c)}[${code(indexNode, c)}] = ${code(y, c)};`
|
|
57
|
+
}
|
|
45
58
|
if (type === 'ternary')
|
|
46
59
|
return c.isWebGL
|
|
47
60
|
? `(${code(z, c)} ? ${code(x, c)} : ${code(y, c)})`
|
|
@@ -91,12 +104,12 @@ export const code = <T extends Constants>(target: X<T>, c?: NodeContext | null):
|
|
|
91
104
|
return c.isWebGL ? `${id}` : `out.${id}`
|
|
92
105
|
}
|
|
93
106
|
if (type === 'builtin') {
|
|
94
|
-
if (c.isWebGL) return getBluiltin(id)
|
|
107
|
+
if (c.isWebGL) return getBluiltin(c, id)
|
|
95
108
|
if (id === 'position') return 'out.position'
|
|
96
109
|
const field = `@builtin(${id}) ${id}: ${getConversions(infer(target, c), c)}`
|
|
97
|
-
if (c.
|
|
98
|
-
|
|
99
|
-
|
|
110
|
+
if (c.label === 'compute') c.code?.computeInputs.set(id, field)
|
|
111
|
+
else if (c.label === 'frag') c.code?.fragInputs.set(id, field)
|
|
112
|
+
else if (c.label === 'vert') c.code?.vertInputs.set(id, field)
|
|
100
113
|
return `in.${id}`
|
|
101
114
|
}
|
|
102
115
|
if (type === 'attribute') {
|
|
@@ -115,6 +128,7 @@ export const code = <T extends Constants>(target: X<T>, c?: NodeContext | null):
|
|
|
115
128
|
target.listeners.add(fun)
|
|
116
129
|
head = parseUniformHead(c, id, varType)
|
|
117
130
|
}
|
|
131
|
+
if (type === 'storage') head = parseStorageHead(c, id, infer(target, c))
|
|
118
132
|
if (type === 'constant') head = parseConstantHead(c, id, infer(target, c), code(x, c))
|
|
119
133
|
if (head) {
|
|
120
134
|
c.code?.headers.set(id, head)
|
package/src/node/utils/infer.ts
CHANGED
|
@@ -31,14 +31,6 @@ const inferOperator = <T extends C>(L: T, R: T, op: string): T => {
|
|
|
31
31
|
return L
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
// Unified logic with infer.ts InferArrayElement type
|
|
35
|
-
const inferArrayElement = <T extends C>(arrayType: T): T => {
|
|
36
|
-
if (arrayType === 'mat4') return 'vec4' as T
|
|
37
|
-
if (arrayType === 'mat3') return 'vec3' as T
|
|
38
|
-
if (arrayType === 'mat2') return 'vec2' as T
|
|
39
|
-
return 'float' as T
|
|
40
|
-
}
|
|
41
|
-
|
|
42
34
|
export const inferPrimitiveType = <T extends C>(x: X) => {
|
|
43
35
|
if (is.bol(x)) return 'bool' as T
|
|
44
36
|
if (is.str(x)) return 'texture' as T
|
|
@@ -74,9 +66,12 @@ export const inferImpl = <T extends C>(target: NodeProxy<T>, c: NodeContext): T
|
|
|
74
66
|
if (type === 'ternary') return inferOperator(infer(y, c), infer(z, c), 'add')
|
|
75
67
|
if (type === 'builtin') return inferBuiltin(id)
|
|
76
68
|
if (type === 'function') return inferFunction(x) || infer(y, c)
|
|
77
|
-
if (type === 'define'
|
|
69
|
+
if (type === 'define') {
|
|
70
|
+
if (isConstants(layout?.type)) return layout?.type as T
|
|
71
|
+
if (!inferFrom || inferFrom.length === 0) return 'void' as T
|
|
72
|
+
return inferFromArray(inferFrom, c)
|
|
73
|
+
}
|
|
78
74
|
if (type === 'attribute' && is.arr(x) && c.gl?.count) return inferFromCount(x.length / c.gl.count)
|
|
79
|
-
if (type === 'element') return inferArrayElement(infer(x, c) as T)
|
|
80
75
|
if (type === 'member') {
|
|
81
76
|
if (isSwizzle(y)) return inferFromCount(y.length)
|
|
82
77
|
if (isNodeProxy(x)) {
|
|
@@ -86,7 +81,7 @@ export const inferImpl = <T extends C>(target: NodeProxy<T>, c: NodeContext): T
|
|
|
86
81
|
return 'float' as T // fallback @TODO FIX
|
|
87
82
|
}
|
|
88
83
|
if (inferFrom) return inferFromArray(inferFrom, c)
|
|
89
|
-
return infer(x, c) // for uniform
|
|
84
|
+
return infer(x, c) // for uniform and storage gather and scatter
|
|
90
85
|
}
|
|
91
86
|
|
|
92
87
|
export const infer = <T extends C>(target: X<T>, c?: NodeContext | null): T => {
|
package/src/node/utils/parse.ts
CHANGED
|
@@ -11,6 +11,35 @@ export const parseArray = (children: X[], c: NodeContext) => {
|
|
|
11
11
|
.join(', ')
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
// only for webgl
|
|
15
|
+
export const parseGather = (c: NodeContext, x: X, y: X, target: X) => {
|
|
16
|
+
const parseSwizzle = () => {
|
|
17
|
+
const valueType = infer(target, c)
|
|
18
|
+
if (valueType === 'float') return '.x'
|
|
19
|
+
if (valueType === 'vec2') return '.xy'
|
|
20
|
+
if (valueType === 'vec3') return '.xyz'
|
|
21
|
+
if (valueType === 'vec4') return ''
|
|
22
|
+
throw new Error(`Unsupported storage scatter type: ${valueType}`)
|
|
23
|
+
}
|
|
24
|
+
const indexVar = code(y, c)
|
|
25
|
+
const texSize = Math.floor(Math.sqrt(c.gl?.particles || 1024))
|
|
26
|
+
const coordX = `int(${indexVar}) % ${texSize}`
|
|
27
|
+
const coordY = `int(${indexVar}) / ${texSize}`
|
|
28
|
+
return `texelFetch(${code(x, c)}, ivec2(${coordX}, ${coordY}), 0)${parseSwizzle()}`
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// only for webgl
|
|
32
|
+
export const parseScatter = (c: NodeContext, storageNode: X, valueNode: X) => {
|
|
33
|
+
const storageId = code(storageNode, c)
|
|
34
|
+
const valueCode = code(valueNode, c)
|
|
35
|
+
const valueType = infer(valueNode, c)
|
|
36
|
+
if (valueType === 'float') return `_${storageId} = vec4(${valueCode}, 0.0, 0.0, 1.0);`
|
|
37
|
+
if (valueType === 'vec2') return `_${storageId} = vec4(${valueCode}, 0.0, 1.0);`
|
|
38
|
+
if (valueType === 'vec3') return `_${storageId} = vec4(${valueCode}, 1.0);`
|
|
39
|
+
if (valueType === 'vec4') return `_${storageId} = ${valueCode};`
|
|
40
|
+
throw new Error(`Unsupported storage scatter type: ${valueType}`)
|
|
41
|
+
}
|
|
42
|
+
|
|
14
43
|
export const parseTexture = (c: NodeContext, y: X, z: X, w: X) => {
|
|
15
44
|
if (c.isWebGL) {
|
|
16
45
|
const args = w ? [y, z, w] : [y, z]
|
|
@@ -118,7 +147,10 @@ export const parseDefine = (c: NodeContext, props: NodeProps, returnType: Consta
|
|
|
118
147
|
ret.push(`${returnType} ${id}(${params}) {`)
|
|
119
148
|
} else {
|
|
120
149
|
for (const [paramId, type] of argParams) params.push(`${paramId}: ${getConversions(type, c)}`)
|
|
121
|
-
|
|
150
|
+
const isVoid = returnType === 'void'
|
|
151
|
+
if (isVoid) {
|
|
152
|
+
ret.push(`fn ${id}(${params}) {`)
|
|
153
|
+
} else ret.push(`fn ${id}(${params}) -> ${getConversions(returnType, c)} {`)
|
|
122
154
|
}
|
|
123
155
|
const scopeCode = code(x, c)
|
|
124
156
|
if (scopeCode) ret.push(scopeCode)
|
|
@@ -135,6 +167,13 @@ export const parseVaryingHead = (c: NodeContext, id: string, type: string) => {
|
|
|
135
167
|
: `@location(${c.code?.vertVaryings?.size || 0}) ${id}: ${getConversions(type, c)}`
|
|
136
168
|
}
|
|
137
169
|
|
|
170
|
+
export const parseAttribHead = (c: NodeContext, id: string, type: Constants) => {
|
|
171
|
+
if (c.isWebGL) return `${type} ${id};`
|
|
172
|
+
const { location = 0 } = c.gl?.webgpu?.attribs.map.get(id) || {}
|
|
173
|
+
const wgslType = getConversions(type, c)
|
|
174
|
+
return `@location(${location}) ${id}: ${wgslType}`
|
|
175
|
+
}
|
|
176
|
+
|
|
138
177
|
export const parseUniformHead = (c: NodeContext, id: string, type: Constants) => {
|
|
139
178
|
const isTexture = type === 'sampler2D' || type === 'texture'
|
|
140
179
|
if (c.isWebGL)
|
|
@@ -153,11 +192,16 @@ export const parseUniformHead = (c: NodeContext, id: string, type: Constants) =>
|
|
|
153
192
|
return `@group(${group}) @binding(${binding}) var<uniform> ${id}: ${wgslType};`
|
|
154
193
|
}
|
|
155
194
|
|
|
156
|
-
export const
|
|
157
|
-
if (c.isWebGL)
|
|
158
|
-
|
|
195
|
+
export const parseStorageHead = (c: NodeContext, id: string, type: Constants) => {
|
|
196
|
+
if (c.isWebGL) {
|
|
197
|
+
const ret = `uniform sampler2D ${id};`
|
|
198
|
+
if (c.label !== 'compute') return ret
|
|
199
|
+
const location = c.units?.(id)
|
|
200
|
+
return `${ret}\nlayout(location = ${location}) out vec4 _${id};` // out texture buffer
|
|
201
|
+
}
|
|
202
|
+
const { group = 0, binding = 0 } = c.gl?.webgpu?.storages.map.get(id) || {}
|
|
159
203
|
const wgslType = getConversions(type, c)
|
|
160
|
-
return `@
|
|
204
|
+
return `@group(${group}) @binding(${binding}) var<storage, read_write> ${id}: array<${wgslType}>;`
|
|
161
205
|
}
|
|
162
206
|
|
|
163
207
|
export const parseConstantHead = (c: NodeContext, id: string, type: Constants, value: string) => {
|
package/src/node/utils/utils.ts
CHANGED
|
@@ -48,8 +48,14 @@ let count = 0
|
|
|
48
48
|
|
|
49
49
|
export const getId = () => `x${count++}`
|
|
50
50
|
|
|
51
|
-
export const getBluiltin = (id: string) => {
|
|
52
|
-
|
|
51
|
+
export const getBluiltin = (c: NodeContext, id: string) => {
|
|
52
|
+
if (id === 'global_invocation_id') {
|
|
53
|
+
const size = Math.floor(Math.sqrt(c.gl?.particles || 1024))
|
|
54
|
+
return `uvec3(uint(gl_FragCoord.y) * uint(${size}) + uint(gl_FragCoord.x), 0u, 0u)`
|
|
55
|
+
}
|
|
56
|
+
const ret = WGSL_TO_GLSL_BUILTIN[id as keyof typeof WGSL_TO_GLSL_BUILTIN]
|
|
57
|
+
if (!ret) throw new Error(`Error: unknown builtin variable ${id}`)
|
|
58
|
+
return ret
|
|
53
59
|
}
|
|
54
60
|
|
|
55
61
|
export const getConversions = <T extends Constants>(x: X<T>, c?: NodeContext) => {
|
|
@@ -95,6 +101,7 @@ export const initNodeContext = (c: NodeContext) => {
|
|
|
95
101
|
vertInputs: new Map(),
|
|
96
102
|
vertOutputs: new Map(),
|
|
97
103
|
vertVaryings: new Map(),
|
|
104
|
+
computeInputs: new Map(),
|
|
98
105
|
dependencies: new Map(),
|
|
99
106
|
}
|
|
100
107
|
if (c.isWebGL) return c
|
package/src/types.ts
CHANGED
|
@@ -18,6 +18,7 @@ export type GL = EventState<{
|
|
|
18
18
|
mouse: [number, number]
|
|
19
19
|
count: number
|
|
20
20
|
loading: number
|
|
21
|
+
particles: 64 | 256 | 576 | 1024 | 1600 | 2304 | 3136 | 4096 | 4096 | 5184 | 6400 // (8k)^2
|
|
21
22
|
el: HTMLCanvasElement
|
|
22
23
|
vs?: string | Vec4
|
|
23
24
|
cs?: string | Vec4
|
|
@@ -117,4 +118,5 @@ export interface WebGPUState {
|
|
|
117
118
|
export interface WebGLState {
|
|
118
119
|
context: WebGLRenderingContext
|
|
119
120
|
program: WebGLProgram
|
|
121
|
+
storages: any
|
|
120
122
|
}
|
package/src/utils/program.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { fragment, vertex } from '../node'
|
|
2
1
|
import { is } from './helpers'
|
|
3
|
-
import type { X } from '../node'
|
|
4
2
|
import type { GL } from '../types'
|
|
5
3
|
|
|
6
4
|
const createShader = (c: WebGLRenderingContext, source: string, type: number, onError = console.warn) => {
|
|
@@ -14,17 +12,13 @@ const createShader = (c: WebGLRenderingContext, source: string, type: number, on
|
|
|
14
12
|
onError(`Could not compile shader: ${error}`)
|
|
15
13
|
}
|
|
16
14
|
|
|
17
|
-
export const createProgram = (c: WebGLRenderingContext,
|
|
18
|
-
if (!vert || !frag) return
|
|
19
|
-
const config = { isWebGL: true, gl }
|
|
20
|
-
frag = fragment(frag, config) // needs to be before vertex
|
|
21
|
-
vert = vertex(vert, config)
|
|
15
|
+
export const createProgram = (c: WebGLRenderingContext, frag: string, vert: string, gl: GL) => {
|
|
22
16
|
const pg = c.createProgram()
|
|
23
|
-
const vs = createShader(c, vert, c.VERTEX_SHADER, gl.error)
|
|
24
17
|
const fs = createShader(c, frag, c.FRAGMENT_SHADER, gl.error)
|
|
18
|
+
const vs = createShader(c, vert, c.VERTEX_SHADER, gl.error)
|
|
25
19
|
if (!fs || !vs) return
|
|
26
|
-
c.attachShader(pg, vs!)
|
|
27
20
|
c.attachShader(pg, fs!)
|
|
21
|
+
c.attachShader(pg, vs!)
|
|
28
22
|
c.linkProgram(pg)
|
|
29
23
|
if (c.getProgramParameter(pg, c.LINK_STATUS)) return pg
|
|
30
24
|
const error = c.getProgramInfoLog(pg)
|
|
@@ -93,20 +87,70 @@ export const createTexture = (c: WebGLRenderingContext, img: HTMLImageElement, l
|
|
|
93
87
|
c.bindTexture(c.TEXTURE_2D, texture)
|
|
94
88
|
}
|
|
95
89
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
90
|
+
/**
|
|
91
|
+
* for gpgpu
|
|
92
|
+
*/
|
|
93
|
+
interface TextureBuffer {
|
|
94
|
+
texture: WebGLTexture
|
|
95
|
+
buffer: WebGLFramebuffer
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export const createStorage = (
|
|
99
|
+
c: WebGL2RenderingContext,
|
|
100
|
+
value: number[],
|
|
101
|
+
size: number,
|
|
102
|
+
ping: TextureBuffer,
|
|
103
|
+
pong: TextureBuffer,
|
|
104
|
+
unit: number,
|
|
105
|
+
array: Float32Array
|
|
106
|
+
) => {
|
|
107
|
+
const particles = size * size
|
|
108
|
+
const vectorSize = value.length / particles
|
|
109
|
+
for (let i = 0; i < particles; i++) {
|
|
110
|
+
for (let j = 0; j < Math.min(vectorSize, 4); j++) {
|
|
111
|
+
array[4 * i + j] = value[i * vectorSize + j] || 0
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
c.activeTexture(c.TEXTURE0 + unit)
|
|
115
|
+
c.bindTexture(c.TEXTURE_2D, ping.texture)
|
|
116
|
+
c.texImage2D(c.TEXTURE_2D, 0, c.RGBA32F, size, size, 0, c.RGBA, c.FLOAT, array)
|
|
102
117
|
c.texParameteri(c.TEXTURE_2D, c.TEXTURE_MIN_FILTER, c.NEAREST)
|
|
103
118
|
c.texParameteri(c.TEXTURE_2D, c.TEXTURE_MAG_FILTER, c.NEAREST)
|
|
104
119
|
c.texParameteri(c.TEXTURE_2D, c.TEXTURE_WRAP_S, c.CLAMP_TO_EDGE)
|
|
105
120
|
c.texParameteri(c.TEXTURE_2D, c.TEXTURE_WRAP_T, c.CLAMP_TO_EDGE)
|
|
106
|
-
c.bindTexture(c.TEXTURE_2D,
|
|
107
|
-
c.texImage2D(c.TEXTURE_2D, 0, c.RGBA32F, size, size, 0, c.RGBA, c.FLOAT,
|
|
121
|
+
c.bindTexture(c.TEXTURE_2D, pong.texture)
|
|
122
|
+
c.texImage2D(c.TEXTURE_2D, 0, c.RGBA32F, size, size, 0, c.RGBA, c.FLOAT, array)
|
|
108
123
|
c.texParameteri(c.TEXTURE_2D, c.TEXTURE_MIN_FILTER, c.NEAREST)
|
|
109
124
|
c.texParameteri(c.TEXTURE_2D, c.TEXTURE_MAG_FILTER, c.NEAREST)
|
|
110
125
|
c.texParameteri(c.TEXTURE_2D, c.TEXTURE_WRAP_S, c.CLAMP_TO_EDGE)
|
|
111
126
|
c.texParameteri(c.TEXTURE_2D, c.TEXTURE_WRAP_T, c.CLAMP_TO_EDGE)
|
|
112
127
|
}
|
|
128
|
+
|
|
129
|
+
export const cleanStorage = (
|
|
130
|
+
c: WebGL2RenderingContext,
|
|
131
|
+
map: Iterable<{ ping: TextureBuffer; pong: TextureBuffer }>
|
|
132
|
+
) => {
|
|
133
|
+
for (const { ping, pong } of map) {
|
|
134
|
+
c.deleteTexture(ping.texture)
|
|
135
|
+
c.deleteTexture(pong.texture)
|
|
136
|
+
c.deleteFramebuffer(ping.buffer)
|
|
137
|
+
c.deleteFramebuffer(pong.buffer)
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export const createAttachment = (
|
|
142
|
+
c: WebGL2RenderingContext,
|
|
143
|
+
i: TextureBuffer,
|
|
144
|
+
o: TextureBuffer,
|
|
145
|
+
loc: WebGLUniformLocation,
|
|
146
|
+
unit: number,
|
|
147
|
+
index: number
|
|
148
|
+
) => {
|
|
149
|
+
c.activeTexture(c.TEXTURE0 + unit)
|
|
150
|
+
c.bindTexture(c.TEXTURE_2D, i.texture)
|
|
151
|
+
c.uniform1i(loc, unit)
|
|
152
|
+
if (index === 0) c.bindFramebuffer(c.FRAMEBUFFER, o.buffer)
|
|
153
|
+
const attachment = c.COLOR_ATTACHMENT0 + index
|
|
154
|
+
c.framebufferTexture2D(c.FRAMEBUFFER, attachment, c.TEXTURE_2D, o.texture, 0)
|
|
155
|
+
return attachment
|
|
156
|
+
}
|