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/webgl.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { nested as cached } from 'reev'
|
|
2
2
|
import { loadingImage } from './utils/helpers'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
cleanStorage,
|
|
5
|
+
createAttachment,
|
|
6
|
+
createAttrib,
|
|
7
|
+
createProgram,
|
|
8
|
+
createStorage,
|
|
9
|
+
createTexture,
|
|
10
|
+
createUniform,
|
|
11
|
+
} from './utils/program'
|
|
12
|
+
import { compute, fragment, vertex } from './node'
|
|
4
13
|
import type { GL, WebGLState } from './types'
|
|
5
14
|
|
|
6
15
|
const vert = /* cpp */ `
|
|
@@ -11,100 +20,103 @@ void main() {
|
|
|
11
20
|
gl_Position = vec4(x, y, 0.0, 1.0);
|
|
12
21
|
}`.trim()
|
|
13
22
|
|
|
14
|
-
|
|
15
|
-
|
|
23
|
+
const computeProgram = (gl: GL, c: WebGL2RenderingContext) => {
|
|
24
|
+
if (!gl.cs) return null // ignore if no compute shader
|
|
16
25
|
c.getExtension('EXT_color_buffer_float')
|
|
17
|
-
const pg1 = createProgram(c, gl.vs, gl.fs, gl)!
|
|
18
|
-
const pg2 = createProgram(c, vert, gl.cs, gl)!
|
|
19
|
-
c.useProgram(pg1)
|
|
20
26
|
|
|
21
27
|
let activeUnit = 0 // for texture units
|
|
22
28
|
let currentNum = 0 // for storage buffers
|
|
23
29
|
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
const units = cached(() => activeUnit++)
|
|
31
|
+
const config = { isWebGL: true, gl, units }
|
|
32
|
+
|
|
33
|
+
const pg = createProgram(c, compute(gl.cs, config), vert, gl)!
|
|
34
|
+
const size = Math.ceil(Math.sqrt(gl.particles))
|
|
35
|
+
|
|
36
|
+
const uniforms = cached((key) => c.getUniformLocation(pg, key)!)
|
|
37
|
+
const storages = cached((key) => {
|
|
38
|
+
const array = new Float32Array(size * size * 4) // RGBA texture data
|
|
39
|
+
const ping = { texture: c.createTexture(), buffer: c.createFramebuffer() }
|
|
40
|
+
const pong = { texture: c.createTexture(), buffer: c.createFramebuffer() }
|
|
41
|
+
return { ping, pong, array, loc: uniforms(key), unit: units(key) }
|
|
33
42
|
})
|
|
34
43
|
|
|
44
|
+
const _uniform = (key: string, value: number | number[]) => {
|
|
45
|
+
c.useProgram(pg)
|
|
46
|
+
createUniform(c, uniforms(key), value)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const _storage = (key: string, value: number[]) => {
|
|
50
|
+
const { ping, pong, unit, array } = storages(key)
|
|
51
|
+
createStorage(c, value, size, ping, pong, unit, array)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const clean = () => {
|
|
55
|
+
c.deleteProgram(pg)
|
|
56
|
+
cleanStorage(c, storages.map.values())
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const render = () => {
|
|
60
|
+
c.useProgram(pg)
|
|
61
|
+
const attachments = storages.map.values().map(({ ping, pong, loc, unit }, index) => {
|
|
62
|
+
const [i, o] = currentNum % 2 ? [ping, pong] : [pong, ping]
|
|
63
|
+
return createAttachment(c, i, o, loc, unit, index)
|
|
64
|
+
})
|
|
65
|
+
c.drawBuffers(attachments)
|
|
66
|
+
c.drawArrays(c.TRIANGLES, 0, 3)
|
|
67
|
+
c.bindFramebuffer(c.FRAMEBUFFER, null)
|
|
68
|
+
currentNum++
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return { render, clean, _uniform, _storage, storages }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export const webgl = async (gl: GL) => {
|
|
75
|
+
const config = { isWebGL: true, gl }
|
|
76
|
+
const c = gl.el!.getContext('webgl2')!
|
|
77
|
+
const cp = computeProgram(gl, c)
|
|
78
|
+
const pg = createProgram(c, fragment(gl.fs, config), vertex(gl.vs, config), gl)!
|
|
79
|
+
c.useProgram(pg)
|
|
80
|
+
|
|
81
|
+
let activeUnit = 0 // for texture units
|
|
82
|
+
|
|
83
|
+
const units = cached(() => activeUnit++)
|
|
84
|
+
const attribs = cached((key) => c.getAttribLocation(pg, key))
|
|
85
|
+
const uniforms = cached((key) => c.getUniformLocation(pg, key))
|
|
86
|
+
|
|
35
87
|
const _attribute = (key = '', value: number[], iboValue: number[]) => {
|
|
36
88
|
const loc = attribs(key, true)
|
|
37
89
|
createAttrib(c, loc, gl.count, value, iboValue)
|
|
38
90
|
}
|
|
39
91
|
|
|
40
92
|
const _uniform = (key: string, value: number | number[]) => {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
createUniform(c, uniforms2(key)!, value)
|
|
45
|
-
c.useProgram(pg1)
|
|
93
|
+
c.useProgram(pg)
|
|
94
|
+
createUniform(c, uniforms(key)!, value)
|
|
95
|
+
cp?._uniform(key, value)
|
|
46
96
|
}
|
|
47
97
|
|
|
48
98
|
const _texture = (key: string, src: string) => {
|
|
99
|
+
c.useProgram(pg)
|
|
49
100
|
loadingImage(gl, src, (source) => {
|
|
50
|
-
|
|
51
|
-
const unit = textures(key)
|
|
52
|
-
createTexture(c, source, loc, unit)
|
|
101
|
+
createTexture(c, source, uniforms(key), units(key))
|
|
53
102
|
})
|
|
54
103
|
}
|
|
55
104
|
|
|
56
|
-
const _storage = (key: string, value: number[] | Float32Array) => {
|
|
57
|
-
const array = value instanceof Float32Array ? value : new Float32Array(value)
|
|
58
|
-
const storage = storages(key)
|
|
59
|
-
const size = Math.ceil(Math.sqrt(array.length))
|
|
60
|
-
storage.width = size
|
|
61
|
-
storage.height = size
|
|
62
|
-
createStorage(c, size, storage, array)
|
|
63
|
-
c.uniform1i(uniforms1(key), storage.unit)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
105
|
const clean = () => {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
for (const { a, b } of storages.map.values()) {
|
|
70
|
-
c.deleteTexture(a.texture)
|
|
71
|
-
c.deleteTexture(b.texture)
|
|
72
|
-
c.deleteFramebuffer(a.buffer)
|
|
73
|
-
c.deleteFramebuffer(b.buffer)
|
|
74
|
-
}
|
|
106
|
+
cp?.clean()
|
|
107
|
+
c.deleteProgram(pg)
|
|
75
108
|
c.getExtension('WEBGL_lose_context')?.loseContext()
|
|
76
109
|
}
|
|
77
110
|
|
|
78
|
-
const _compute = () => {
|
|
79
|
-
c.useProgram(pg2)
|
|
80
|
-
for (const [, storage] of storages.map) {
|
|
81
|
-
const output = currentNum % 2 ? storage.b : storage.a
|
|
82
|
-
c.bindFramebuffer(c.FRAMEBUFFER, output.buffer)
|
|
83
|
-
c.framebufferTexture2D(c.FRAMEBUFFER, c.COLOR_ATTACHMENT0, c.TEXTURE_2D, output.texture, 0)
|
|
84
|
-
c.viewport(0, 0, storage.width, storage.height)
|
|
85
|
-
c.drawArrays(c.TRIANGLES, 0, 6)
|
|
86
|
-
c.bindFramebuffer(c.FRAMEBUFFER, null)
|
|
87
|
-
}
|
|
88
|
-
currentNum++
|
|
89
|
-
c.useProgram(pg1)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
111
|
const render = () => {
|
|
93
|
-
|
|
94
|
-
c.
|
|
95
|
-
c.clear(c.COLOR_BUFFER_BIT)
|
|
112
|
+
cp?.render()
|
|
113
|
+
c.useProgram(pg)
|
|
96
114
|
c.viewport(0, 0, ...gl.size)
|
|
97
|
-
for (const [key, { unit, a, b }] of storages.map) {
|
|
98
|
-
const loc = uniforms1(key)
|
|
99
|
-
const output = currentNum % 2 ? a : b
|
|
100
|
-
c.activeTexture(c.TEXTURE0 + unit)
|
|
101
|
-
c.bindTexture(c.TEXTURE_2D, output.texture)
|
|
102
|
-
c.uniform1i(loc, unit)
|
|
103
|
-
}
|
|
104
115
|
c.drawArrays(c.TRIANGLES, 0, gl.count)
|
|
116
|
+
c.bindFramebuffer(c.FRAMEBUFFER, null)
|
|
105
117
|
}
|
|
106
118
|
|
|
107
|
-
const webgl: WebGLState = { context: c, program:
|
|
119
|
+
const webgl: WebGLState = { context: c, program: pg, storages: cp?.storages }
|
|
108
120
|
|
|
109
|
-
return { webgl, render, clean, _attribute, _uniform, _texture, _storage }
|
|
121
|
+
return { webgl, render, clean, _attribute, _uniform, _texture, _storage: cp?._storage }
|
|
110
122
|
}
|
package/src/webgpu.ts
CHANGED
|
@@ -2,8 +2,8 @@ import { nested as cached } from 'reev'
|
|
|
2
2
|
import { is, loadingImage } from './utils/helpers'
|
|
3
3
|
import {
|
|
4
4
|
createArrayBuffer,
|
|
5
|
-
createBindings,
|
|
6
5
|
createBindGroup,
|
|
6
|
+
createBindings,
|
|
7
7
|
createComputePipeline,
|
|
8
8
|
createDepthTexture,
|
|
9
9
|
createDescriptor,
|
|
@@ -15,15 +15,53 @@ import {
|
|
|
15
15
|
import type { GL, WebGPUState } from './types'
|
|
16
16
|
import { compute, fragment, vertex } from './node'
|
|
17
17
|
|
|
18
|
+
const WORKING_GROUP_SIZE = 32
|
|
19
|
+
|
|
20
|
+
const computeProgram = (gl: GL, device: GPUDevice, bindings: any) => {
|
|
21
|
+
let flush = (_pass: GPUComputePassEncoder) => {}
|
|
22
|
+
|
|
23
|
+
const storages = cached((_key, value: number[] | Float32Array) => {
|
|
24
|
+
const { array, buffer } = createArrayBuffer(device, value, 'storage')
|
|
25
|
+
const { binding, group } = bindings.storage()
|
|
26
|
+
return { array, buffer, binding, group }
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
const _storage = (key: string, value: number[] | Float32Array) => {
|
|
30
|
+
const { array, buffer } = storages(key, value)
|
|
31
|
+
device.queue.writeBuffer(buffer, 0, array as any)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const update = (bindGroups: GPUBindGroup[], bindGroupLayouts: GPUBindGroupLayout[], comp: string) => {
|
|
35
|
+
const pipeline = createComputePipeline(device, bindGroupLayouts, comp!)
|
|
36
|
+
flush = (pass) => {
|
|
37
|
+
pass.setPipeline(pipeline)
|
|
38
|
+
bindGroups.forEach((v, i) => pass.setBindGroup(i, v))
|
|
39
|
+
const workgroupCount = Math.ceil(gl.particles / WORKING_GROUP_SIZE)
|
|
40
|
+
pass.dispatchWorkgroups(workgroupCount, 1, 1)
|
|
41
|
+
pass.end()
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const render = (pass: GPUComputePassEncoder) => {
|
|
46
|
+
flush(pass)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const clean = () => {
|
|
50
|
+
for (const { buffer } of storages.map.values()) buffer.destroy()
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return { storages, _storage, update, render, clean }
|
|
54
|
+
}
|
|
55
|
+
|
|
18
56
|
export const webgpu = async (gl: GL) => {
|
|
19
57
|
const context = gl.el!.getContext('webgpu') as GPUCanvasContext
|
|
20
58
|
const { device, format } = await createDevice(context, gl.error)
|
|
21
59
|
const bindings = createBindings()
|
|
60
|
+
const cp = computeProgram(gl, device, bindings)
|
|
22
61
|
let frag: string
|
|
23
|
-
let vert: string
|
|
24
62
|
let comp: string
|
|
63
|
+
let vert: string
|
|
25
64
|
let flush = (_pass: GPURenderPassEncoder) => {}
|
|
26
|
-
let computeFlush = (_pass: GPUComputePassEncoder) => {}
|
|
27
65
|
let needsUpdate = true
|
|
28
66
|
let depthTexture: GPUTexture
|
|
29
67
|
|
|
@@ -35,13 +73,6 @@ export const webgpu = async (gl: GL) => {
|
|
|
35
73
|
return { array, buffer, location, stride }
|
|
36
74
|
})
|
|
37
75
|
|
|
38
|
-
const storages = cached((_key, value: number[] | Float32Array) => {
|
|
39
|
-
needsUpdate = true
|
|
40
|
-
const { array, buffer } = createArrayBuffer(device, value, 'storage')
|
|
41
|
-
const { binding, group } = bindings.storage()
|
|
42
|
-
return { array, buffer, binding, group }
|
|
43
|
-
})
|
|
44
|
-
|
|
45
76
|
const uniforms = cached((_key, value: number[]) => {
|
|
46
77
|
needsUpdate = true
|
|
47
78
|
const { binding, group } = bindings.uniform()
|
|
@@ -61,14 +92,10 @@ export const webgpu = async (gl: GL) => {
|
|
|
61
92
|
device.queue.writeBuffer(buffer, 0, array as any)
|
|
62
93
|
}
|
|
63
94
|
|
|
64
|
-
const _storage = (key: string, value: number[] | Float32Array) => {
|
|
65
|
-
const { array, buffer } = storages(key, value)
|
|
66
|
-
device.queue.writeBuffer(buffer, 0, array as any)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
95
|
const _uniform = (key: string, value: number | number[]) => {
|
|
70
96
|
if (is.num(value)) value = [value]
|
|
71
97
|
const { array, buffer } = uniforms(key, value)
|
|
98
|
+
array.set(value) // needs to set leatest value
|
|
72
99
|
device.queue.writeBuffer(buffer, 0, array as any)
|
|
73
100
|
}
|
|
74
101
|
|
|
@@ -86,7 +113,7 @@ export const webgpu = async (gl: GL) => {
|
|
|
86
113
|
device,
|
|
87
114
|
uniforms.map.values(),
|
|
88
115
|
textures.map.values(),
|
|
89
|
-
storages.map.values()
|
|
116
|
+
cp.storages.map.values()
|
|
90
117
|
)
|
|
91
118
|
const pipeline = createPipeline(device, format, bufferLayouts, bindGroupLayouts, vert, frag)
|
|
92
119
|
flush = (pass) => {
|
|
@@ -96,33 +123,21 @@ export const webgpu = async (gl: GL) => {
|
|
|
96
123
|
pass.draw(gl.count, 1, 0, 0)
|
|
97
124
|
pass.end()
|
|
98
125
|
}
|
|
99
|
-
if (comp)
|
|
100
|
-
const computePipeline = createComputePipeline(device, bindGroupLayouts, comp)
|
|
101
|
-
computeFlush = (pass) => {
|
|
102
|
-
pass.setPipeline(computePipeline)
|
|
103
|
-
bindGroups.forEach((v, i) => pass.setBindGroup(i, v))
|
|
104
|
-
let maxElements = 1
|
|
105
|
-
for (const { array } of storages.map.values())
|
|
106
|
-
maxElements = Math.max(maxElements, array.length)
|
|
107
|
-
const workgroupCount = Math.ceil(maxElements / 64)
|
|
108
|
-
pass.dispatchWorkgroups(workgroupCount)
|
|
109
|
-
pass.end()
|
|
110
|
-
}
|
|
111
|
-
}
|
|
126
|
+
if (gl.cs) cp.update(bindGroups, bindGroupLayouts, comp)
|
|
112
127
|
}
|
|
113
128
|
|
|
114
129
|
const render = () => {
|
|
115
130
|
if (!frag || !vert) {
|
|
116
131
|
const config = { isWebGL: false, gl }
|
|
117
132
|
frag = fragment(gl.fs, config) // needs to be before vertex
|
|
118
|
-
comp = compute(gl.cs, config)
|
|
119
133
|
vert = vertex(gl.vs, config)
|
|
134
|
+
comp = compute(gl.cs, config)
|
|
120
135
|
}
|
|
121
136
|
if (gl.loading) return // MEMO: loading after build node
|
|
122
137
|
if (needsUpdate) update()
|
|
123
138
|
needsUpdate = false
|
|
124
139
|
const encoder = device.createCommandEncoder()
|
|
125
|
-
if (
|
|
140
|
+
if (gl.cs) cp.render(encoder.beginComputePass())
|
|
126
141
|
flush(encoder.beginRenderPass(createDescriptor(context, depthTexture)))
|
|
127
142
|
device.queue.submit([encoder.finish()])
|
|
128
143
|
}
|
|
@@ -139,19 +154,12 @@ export const webgpu = async (gl: GL) => {
|
|
|
139
154
|
for (const { texture } of textures.map.values()) texture.destroy()
|
|
140
155
|
for (const { buffer } of uniforms.map.values()) buffer.destroy()
|
|
141
156
|
for (const { buffer } of attribs.map.values()) buffer.destroy()
|
|
142
|
-
|
|
157
|
+
cp.clean()
|
|
143
158
|
}
|
|
144
159
|
|
|
145
160
|
resize()
|
|
146
161
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
resize,
|
|
151
|
-
clean,
|
|
152
|
-
_attribute,
|
|
153
|
-
_uniform,
|
|
154
|
-
_texture,
|
|
155
|
-
_storage,
|
|
156
|
-
}
|
|
162
|
+
const webgpu = { device, uniforms, textures, attribs, storages: cp.storages } as WebGPUState
|
|
163
|
+
|
|
164
|
+
return { webgpu, render, resize, clean, _attribute, _uniform, _texture, _storage: cp._storage }
|
|
157
165
|
}
|