glre 0.31.0 → 0.33.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 +34 -64
- package/dist/index.cjs.map +1 -1
- package/dist/{index.d.cts → index.d.ts} +184 -191
- package/dist/index.js +34 -64
- package/dist/index.js.map +1 -1
- package/dist/native.cjs +34 -64
- package/dist/native.cjs.map +1 -1
- package/dist/native.d.ts +54 -0
- package/dist/native.js +34 -64
- package/dist/native.js.map +1 -1
- package/dist/react.cjs +34 -64
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.ts +8 -0
- package/dist/react.js +34 -64
- package/dist/react.js.map +1 -1
- package/dist/solid.cjs +34 -64
- package/dist/solid.cjs.map +1 -1
- package/dist/solid.d.ts +8 -0
- package/dist/solid.js +34 -64
- package/dist/solid.js.map +1 -1
- package/package.json +7 -6
- package/src/index.ts +19 -5
- package/src/node/code.ts +79 -77
- package/src/node/const.ts +27 -44
- package/src/node/index.ts +98 -12
- package/src/node/infer.ts +32 -15
- package/src/node/node.ts +20 -21
- package/src/node/parse.ts +160 -0
- package/src/node/scope.ts +48 -23
- package/src/node/types.ts +100 -57
- package/src/node/utils.ts +63 -94
- package/src/types.ts +32 -16
- package/src/utils/pipeline.ts +136 -95
- package/src/utils/program.ts +7 -36
- package/src/webgl.ts +7 -3
- package/src/webgpu.ts +82 -58
- package/dist/native.d.cts +0 -53
- package/dist/react.d.cts +0 -8
- package/dist/solid.d.cts +0 -8
package/src/types.ts
CHANGED
|
@@ -1,16 +1,7 @@
|
|
|
1
|
-
import { EventState } from 'reev'
|
|
1
|
+
import type { EventState, Nested } from 'reev'
|
|
2
2
|
import type { Fun, Queue, Frame } from 'refr'
|
|
3
3
|
import type { NodeProxy } from './node'
|
|
4
4
|
export type { Fun, Queue, Frame }
|
|
5
|
-
export type GPUContext = any // GPUCanvasContext https://developer.mozilla.org/en-US/docs/Web/API/GPUCanvasContext
|
|
6
|
-
export type GPUDevice = any //
|
|
7
|
-
export type GPUBuffer = any //
|
|
8
|
-
export type GPUPipeline = any //
|
|
9
|
-
export type GPUBindGroup = any
|
|
10
|
-
export type Uniform = number | number[]
|
|
11
|
-
export type Attribute = number[]
|
|
12
|
-
export type Attributes = Record<string, Attribute>
|
|
13
|
-
export type Uniforms = Record<string, Uniform>
|
|
14
5
|
export type PrecisionMode = 'highp' | 'mediump' | 'lowp'
|
|
15
6
|
export type GLClearMode = 'COLOR_BUFFER_BIT' | 'DEPTH_BUFFER_BIT' | 'STENCIL_BUFFER_BIT'
|
|
16
7
|
export type GLDrawType = 'UNSIGNED_BYTE' | 'UNSIGNED_SHORT' | 'UNSIGNED_INT'
|
|
@@ -23,6 +14,28 @@ export type GLDrawMode =
|
|
|
23
14
|
| 'TRIANGLE_FAN'
|
|
24
15
|
| 'TRIANGLES'
|
|
25
16
|
|
|
17
|
+
export interface UniformData {
|
|
18
|
+
array: Float32Array
|
|
19
|
+
buffer: GPUBuffer
|
|
20
|
+
binding: number
|
|
21
|
+
group: number
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface TextureData {
|
|
25
|
+
binding: number
|
|
26
|
+
group: number
|
|
27
|
+
texture: GPUTexture
|
|
28
|
+
sampler: GPUSampler
|
|
29
|
+
view: GPUTextureView
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface AttribData {
|
|
33
|
+
array: Float32Array
|
|
34
|
+
buffer: GPUBuffer
|
|
35
|
+
location: number
|
|
36
|
+
stride: number
|
|
37
|
+
}
|
|
38
|
+
|
|
26
39
|
export interface WebGLState {
|
|
27
40
|
context: WebGLRenderingContext
|
|
28
41
|
program: WebGLProgram
|
|
@@ -30,14 +43,16 @@ export interface WebGLState {
|
|
|
30
43
|
|
|
31
44
|
export interface WebGPUState {
|
|
32
45
|
device: GPUDevice
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
resources: any[]
|
|
37
|
-
loadingImg: number
|
|
38
|
-
needsUpdate: boolean
|
|
46
|
+
uniforms: Nested<UniformData>
|
|
47
|
+
textures: Nested<TextureData>
|
|
48
|
+
attribs: Nested<AttribData>
|
|
39
49
|
}
|
|
40
50
|
|
|
51
|
+
export type Uniform = number | number[]
|
|
52
|
+
export type Attribute = number[]
|
|
53
|
+
export type Attributes = Record<string, Attribute>
|
|
54
|
+
export type Uniforms = Record<string, Uniform>
|
|
55
|
+
|
|
41
56
|
export type GL = EventState<{
|
|
42
57
|
/**
|
|
43
58
|
* initial value
|
|
@@ -84,6 +99,7 @@ export type GL = EventState<{
|
|
|
84
99
|
*/
|
|
85
100
|
_uniform?(key: string, value: Uniform, isMatrix?: boolean): GL
|
|
86
101
|
uniform(key: string, value: Uniform, isMatrix?: boolean): GL
|
|
102
|
+
uniform(node: NodeProxy): GL
|
|
87
103
|
uniform(target: { [key: string]: Uniform }): GL
|
|
88
104
|
_texture?(key: string, value: string): GL
|
|
89
105
|
texture(key: string, value: string): GL
|
package/src/utils/pipeline.ts
CHANGED
|
@@ -1,135 +1,176 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { NodeProxy } from '../node'
|
|
3
|
-
import type { GPUContext, GPUDevice, GPUPipeline } from '../types'
|
|
1
|
+
import type { AttribData, TextureData, UniformData } from '../types'
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
/**
|
|
4
|
+
* initialize
|
|
5
|
+
*/
|
|
6
|
+
export const createDevice = async (c: GPUCanvasContext) => {
|
|
7
|
+
const gpu = navigator.gpu
|
|
8
|
+
const format = gpu.getPreferredCanvasFormat()
|
|
9
|
+
const adapter = await gpu.requestAdapter()
|
|
10
|
+
const device = await adapter!.requestDevice()
|
|
11
|
+
c.configure({ device, format, alphaMode: 'opaque' })
|
|
12
|
+
return { device, format }
|
|
11
13
|
}
|
|
12
|
-
`
|
|
13
14
|
|
|
14
|
-
const
|
|
15
|
-
|
|
15
|
+
export const createBindings = () => {
|
|
16
|
+
let uniform = 0
|
|
17
|
+
let texture = 0
|
|
18
|
+
let attrib = 0
|
|
19
|
+
return {
|
|
20
|
+
uniform: () => {
|
|
21
|
+
const group = Math.floor(uniform / 12)
|
|
22
|
+
const binding = uniform % 12
|
|
23
|
+
uniform++
|
|
24
|
+
return { group, binding }
|
|
25
|
+
},
|
|
26
|
+
texture: () => {
|
|
27
|
+
const baseGroup = Math.floor(uniform / 12) + 1
|
|
28
|
+
const group = baseGroup + Math.floor(texture / 6)
|
|
29
|
+
const binding = (texture % 6) * 2
|
|
30
|
+
texture++
|
|
31
|
+
return { group, binding }
|
|
32
|
+
},
|
|
33
|
+
attrib: () => {
|
|
34
|
+
const location = attrib
|
|
35
|
+
attrib++
|
|
36
|
+
return { location }
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
}
|
|
16
40
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
41
|
+
/**
|
|
42
|
+
* pipeline update
|
|
43
|
+
*/
|
|
44
|
+
const getVertexFormat = (stride: number): GPUVertexFormat => {
|
|
45
|
+
if (stride === 2) return 'float32x2'
|
|
46
|
+
if (stride === 3) return 'float32x3'
|
|
47
|
+
if (stride === 4) return 'float32x4'
|
|
48
|
+
return 'float32'
|
|
20
49
|
}
|
|
21
|
-
`
|
|
22
50
|
|
|
23
|
-
export const
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
51
|
+
export const createVertexBuffers = (attribs: Iterable<AttribData>) => {
|
|
52
|
+
const vertexBuffers: GPUBuffer[] = []
|
|
53
|
+
const bufferLayouts: GPUVertexBufferLayout[] = []
|
|
54
|
+
for (const { buffer, location, stride } of attribs) {
|
|
55
|
+
vertexBuffers[location] = buffer
|
|
56
|
+
bufferLayouts[location] = {
|
|
57
|
+
arrayStride: stride * 4,
|
|
58
|
+
attributes: [
|
|
59
|
+
{
|
|
60
|
+
shaderLocation: location,
|
|
61
|
+
offset: 0,
|
|
62
|
+
format: getVertexFormat(stride),
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return { vertexBuffers, bufferLayouts }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export const createBindGroup = (
|
|
71
|
+
device: GPUDevice,
|
|
72
|
+
uniforms: Iterable<UniformData>,
|
|
73
|
+
textures: Iterable<TextureData>
|
|
74
|
+
) => {
|
|
75
|
+
const groups = new Map<number, { layouts: GPUBindGroupLayoutEntry[]; bindings: GPUBindGroupEntry[] }>()
|
|
76
|
+
const ret = { bindGroups: [] as GPUBindGroup[], bindGroupLayouts: [] as GPUBindGroupLayout[] }
|
|
77
|
+
const add = (i: number, layout: GPUBindGroupLayoutEntry, binding: GPUBindGroupEntry) => {
|
|
78
|
+
if (!groups.has(i)) groups.set(i, { layouts: [], bindings: [] })
|
|
79
|
+
const { layouts, bindings } = groups.get(i)!
|
|
80
|
+
layouts.push(layout)
|
|
81
|
+
bindings.push(binding)
|
|
82
|
+
}
|
|
83
|
+
for (const { binding, buffer, group: i } of uniforms) {
|
|
84
|
+
add(i, { binding, visibility: 3, buffer: { type: 'uniform' } }, { binding, resource: { buffer } })
|
|
85
|
+
}
|
|
86
|
+
for (const { binding: b, group: i, sampler, view } of textures) {
|
|
87
|
+
add(i, { binding: b, visibility: 2, sampler: {} }, { binding: b, resource: sampler })
|
|
88
|
+
add(i, { binding: b + 1, visibility: 2, texture: {} }, { binding: b + 1, resource: view })
|
|
89
|
+
}
|
|
90
|
+
for (const [i, { layouts, bindings }] of groups) {
|
|
91
|
+
ret.bindGroupLayouts[i] = device.createBindGroupLayout({ entries: layouts })
|
|
92
|
+
ret.bindGroups[i] = device.createBindGroup({ layout: ret.bindGroupLayouts[i], entries: bindings })
|
|
93
|
+
}
|
|
94
|
+
return ret
|
|
30
95
|
}
|
|
31
96
|
|
|
32
97
|
export const createPipeline = (
|
|
33
98
|
device: GPUDevice,
|
|
34
|
-
format:
|
|
35
|
-
bufferLayouts:
|
|
36
|
-
bindGroupLayouts:
|
|
37
|
-
vs: string
|
|
38
|
-
fs: string
|
|
99
|
+
format: GPUTextureFormat,
|
|
100
|
+
bufferLayouts: GPUVertexBufferLayout[],
|
|
101
|
+
bindGroupLayouts: GPUBindGroupLayout[],
|
|
102
|
+
vs: string,
|
|
103
|
+
fs: string
|
|
39
104
|
) => {
|
|
40
|
-
if (isNodeProxy(vs)) vs = vertex(vs, { isWebGL: false })
|
|
41
|
-
if (isNodeProxy(fs)) fs = fragment(fs, { isWebGL: false })
|
|
42
|
-
const layout = device.createPipelineLayout({ bindGroupLayouts })
|
|
43
105
|
return device.createRenderPipeline({
|
|
44
106
|
vertex: {
|
|
45
|
-
module: device.createShaderModule({ code: vs
|
|
107
|
+
module: device.createShaderModule({ label: 'vert', code: vs }),
|
|
46
108
|
entryPoint: 'main',
|
|
47
109
|
buffers: bufferLayouts,
|
|
48
110
|
},
|
|
49
111
|
fragment: {
|
|
50
|
-
module: device.createShaderModule({ code: fs
|
|
112
|
+
module: device.createShaderModule({ label: 'frag', code: fs }),
|
|
51
113
|
entryPoint: 'main',
|
|
52
114
|
targets: [{ format }],
|
|
53
115
|
},
|
|
54
|
-
layout,
|
|
116
|
+
layout: device.createPipelineLayout({ bindGroupLayouts }),
|
|
55
117
|
primitive: { topology: 'triangle-list' },
|
|
56
|
-
|
|
118
|
+
depthStencil: {
|
|
119
|
+
depthWriteEnabled: true,
|
|
120
|
+
depthCompare: 'less',
|
|
121
|
+
format: 'depth24plus',
|
|
122
|
+
},
|
|
123
|
+
})
|
|
57
124
|
}
|
|
58
125
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
const layout = device.createBindGroupLayout({ entries: entries0 })
|
|
74
|
-
const bindGroup = device.createBindGroup({ layout, entries: entries1 })
|
|
75
|
-
return { layout, bindGroup }
|
|
126
|
+
/**
|
|
127
|
+
* buffers
|
|
128
|
+
*/
|
|
129
|
+
export const createUniformBuffer = (device: GPUDevice, value: number[]) => {
|
|
130
|
+
const array = new Float32Array(value)
|
|
131
|
+
const size = Math.ceil(array.byteLength / 256) * 256
|
|
132
|
+
const buffer = device.createBuffer({ size, usage: 72 }) // 72 is GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
|
|
133
|
+
return { array, buffer }
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export const createAttribBuffer = (device: GPUDevice, value: number[]) => {
|
|
137
|
+
const array = new Float32Array(value)
|
|
138
|
+
const buffer = device.createBuffer({ size: array.byteLength, usage: 40 }) // 40 is GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
|
|
139
|
+
return { array, buffer }
|
|
76
140
|
}
|
|
77
141
|
|
|
78
|
-
export const createDescriptor = (c:
|
|
142
|
+
export const createDescriptor = (c: GPUCanvasContext, depthTexture: GPUTexture) => {
|
|
79
143
|
return {
|
|
80
144
|
colorAttachments: [
|
|
81
145
|
{
|
|
82
146
|
view: c.getCurrentTexture().createView(),
|
|
83
147
|
clearValue: { r: 0, g: 0, b: 0, a: 1 },
|
|
84
|
-
loadOp: 'clear',
|
|
85
|
-
storeOp: 'store',
|
|
148
|
+
loadOp: 'clear' as GPULoadOp,
|
|
149
|
+
storeOp: 'store' as GPUStoreOp,
|
|
86
150
|
},
|
|
87
151
|
],
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const buffer = device.createBuffer({ size: array.byteLength, usage: 40 }) // 40 === // GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
|
|
96
|
-
return { array, buffer }
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export const createUniformBuffer = (device: GPUDevice, value: number[]) => {
|
|
100
|
-
const array = new Float32Array(value)
|
|
101
|
-
const size = alignTo256(array.byteLength)
|
|
102
|
-
const buffer = device.createBuffer({ size, usage: 72 }) as Buffer // 72 === GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
|
|
103
|
-
return { array, buffer }
|
|
152
|
+
depthStencilAttachment: {
|
|
153
|
+
view: depthTexture.createView(),
|
|
154
|
+
depthClearValue: 1.0,
|
|
155
|
+
depthLoadOp: 'clear' as GPULoadOp,
|
|
156
|
+
depthStoreOp: 'store' as GPUStoreOp,
|
|
157
|
+
},
|
|
158
|
+
} as GPURenderPassDescriptor
|
|
104
159
|
}
|
|
105
160
|
|
|
161
|
+
/**
|
|
162
|
+
* textures
|
|
163
|
+
*/
|
|
106
164
|
export const createTextureSampler = (device: GPUDevice, width = 1280, height = 800) => {
|
|
107
|
-
const texture = device.createTexture({ size: [width, height], format: 'rgba8unorm', usage: 22 })
|
|
165
|
+
const texture = device.createTexture({ size: [width, height], format: 'rgba8unorm', usage: 22 }) // 22 is GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT
|
|
108
166
|
const sampler = device.createSampler({ magFilter: 'linear', minFilter: 'linear' })
|
|
109
167
|
return { texture, sampler }
|
|
110
168
|
}
|
|
111
169
|
|
|
112
|
-
const
|
|
113
|
-
return
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if (stride === 3) return 'float32x3'
|
|
119
|
-
if (stride === 4) return 'float32x4'
|
|
120
|
-
return 'float32'
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export const createBufferLayout = (shaderLocation: number, dataLength: number, count = 6) => {
|
|
124
|
-
const stride = getVertexStride(dataLength, count)
|
|
125
|
-
return {
|
|
126
|
-
arrayStride: stride * 4,
|
|
127
|
-
attributes: [
|
|
128
|
-
{
|
|
129
|
-
shaderLocation,
|
|
130
|
-
offset: 0,
|
|
131
|
-
format: getVertexFormat(stride),
|
|
132
|
-
},
|
|
133
|
-
],
|
|
134
|
-
}
|
|
170
|
+
export const createDepthTexture = (device: GPUDevice, width: number, height: number) => {
|
|
171
|
+
return device.createTexture({
|
|
172
|
+
size: [width, height],
|
|
173
|
+
format: 'depth24plus',
|
|
174
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT,
|
|
175
|
+
})
|
|
135
176
|
}
|
package/src/utils/program.ts
CHANGED
|
@@ -1,25 +1,3 @@
|
|
|
1
|
-
import { fragment, isNodeProxy, vertex } from '../node'
|
|
2
|
-
import type { NodeProxy } from '../node'
|
|
3
|
-
|
|
4
|
-
export const defaultVertexGLSL = /* cpp */ `
|
|
5
|
-
#version 300 es
|
|
6
|
-
void main() {
|
|
7
|
-
float x = float(gl_VertexID % 2) * 4.0 - 1.0;
|
|
8
|
-
float y = float(gl_VertexID / 2) * 4.0 - 1.0;
|
|
9
|
-
gl_Position = vec4(x, y, 0.0, 1.0);
|
|
10
|
-
}
|
|
11
|
-
`
|
|
12
|
-
|
|
13
|
-
export const defaultFragmentGLSL = /* cpp */ `
|
|
14
|
-
#version 300 es
|
|
15
|
-
precision mediump float;
|
|
16
|
-
uniform vec2 iResolution;
|
|
17
|
-
out vec4 fragColor;
|
|
18
|
-
void main() {
|
|
19
|
-
fragColor = vec4(fract(gl_FragCoord.xy / iResolution), 0, 1);
|
|
20
|
-
}
|
|
21
|
-
`
|
|
22
|
-
|
|
23
1
|
const createShader = (c: WebGLRenderingContext, source: string, type: number) => {
|
|
24
2
|
const shader = c.createShader(type)
|
|
25
3
|
if (!shader) throw new Error('Failed to create shader')
|
|
@@ -31,26 +9,19 @@ const createShader = (c: WebGLRenderingContext, source: string, type: number) =>
|
|
|
31
9
|
console.warn(`Could not compile shader: ${error}`)
|
|
32
10
|
}
|
|
33
11
|
|
|
34
|
-
export const createProgram = (
|
|
35
|
-
c: WebGLRenderingContext,
|
|
36
|
-
vs: string | NodeProxy = defaultVertexGLSL,
|
|
37
|
-
fs: string | NodeProxy = defaultFragmentGLSL,
|
|
38
|
-
onError = () => {}
|
|
39
|
-
) => {
|
|
40
|
-
if (isNodeProxy(fs)) fs = fragment(fs, { isWebGL: true })
|
|
41
|
-
if (isNodeProxy(vs)) vs = vertex(fs, { isWebGL: true })
|
|
12
|
+
export const createProgram = (c: WebGLRenderingContext, vert: string, frag: string, onError = () => {}) => {
|
|
42
13
|
const pg = c.createProgram()
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
if (!
|
|
46
|
-
c.attachShader(pg,
|
|
47
|
-
c.attachShader(pg,
|
|
14
|
+
const fs = createShader(c, frag, c.FRAGMENT_SHADER)
|
|
15
|
+
const vs = createShader(c, vert, c.VERTEX_SHADER)
|
|
16
|
+
if (!fs || !vs) return onError()
|
|
17
|
+
c.attachShader(pg, vs)
|
|
18
|
+
c.attachShader(pg, fs)
|
|
48
19
|
c.linkProgram(pg)
|
|
49
20
|
if (c.getProgramParameter(pg, c.LINK_STATUS)) return pg
|
|
50
21
|
const error = c.getProgramInfoLog(pg)
|
|
51
22
|
c.deleteProgram(pg)
|
|
52
23
|
onError()
|
|
53
|
-
console.warn(`Could not link
|
|
24
|
+
console.warn(`Could not link program: ${error}`)
|
|
54
25
|
}
|
|
55
26
|
|
|
56
27
|
export const createVbo = (c: WebGLRenderingContext, data: number[]) => {
|
package/src/webgl.ts
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
import { nested as cached } from 'reev'
|
|
2
|
+
import { fragment, vertex } from './node'
|
|
2
3
|
import { is } from './utils/helpers'
|
|
3
4
|
import { createAttrib, createIbo, createProgram, createTexture, createVbo, getStride } from './utils/program'
|
|
4
5
|
import type { GL, WebGLState } from './types'
|
|
5
6
|
|
|
6
7
|
export const webgl = async (gl: Partial<GL>) => {
|
|
7
8
|
const c = gl.el!.getContext('webgl2')!
|
|
8
|
-
const
|
|
9
|
+
const config = { isWebGL: true, gl }
|
|
10
|
+
const fs = fragment(gl.fs, config)
|
|
11
|
+
const vs = vertex(gl.vs, config)
|
|
12
|
+
const pg = createProgram(c, vs, fs, () => void (gl.isLoop = false))!
|
|
9
13
|
c.useProgram(pg)
|
|
14
|
+
|
|
10
15
|
let _activeUnit = 0
|
|
11
16
|
const uniforms = cached((key) => c.getUniformLocation(pg, key))
|
|
12
17
|
const attribs = cached((key) => c.getAttribLocation(pg, key))
|
|
13
18
|
const units = cached(() => _activeUnit++)
|
|
14
|
-
const state = { context: c, program: pg } as WebGLState
|
|
15
19
|
|
|
16
20
|
const clean = () => c.deleteProgram(pg)
|
|
17
21
|
|
|
@@ -48,5 +52,5 @@ export const webgl = async (gl: Partial<GL>) => {
|
|
|
48
52
|
})
|
|
49
53
|
}
|
|
50
54
|
|
|
51
|
-
return {
|
|
55
|
+
return { render, clean, _attribute, _uniform, _texture, webgl: { context: c, program: pg } as WebGLState }
|
|
52
56
|
}
|
package/src/webgpu.ts
CHANGED
|
@@ -1,84 +1,97 @@
|
|
|
1
1
|
import { nested as cached } from 'reev'
|
|
2
2
|
import { is } from './utils/helpers'
|
|
3
3
|
import {
|
|
4
|
+
createAttribBuffer,
|
|
5
|
+
createBindings,
|
|
6
|
+
createBindGroup,
|
|
7
|
+
createDepthTexture,
|
|
8
|
+
createDescriptor,
|
|
4
9
|
createDevice,
|
|
5
10
|
createPipeline,
|
|
6
|
-
createDescriptor,
|
|
7
|
-
createUniformBuffer,
|
|
8
|
-
createBindGroup,
|
|
9
11
|
createTextureSampler,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
createUniformBuffer,
|
|
13
|
+
createVertexBuffers,
|
|
12
14
|
} from './utils/pipeline'
|
|
13
15
|
import type { GL, WebGPUState } from './types'
|
|
16
|
+
import { fragment, vertex } from './node'
|
|
14
17
|
|
|
15
18
|
export const webgpu = async (gl: Partial<GL>) => {
|
|
16
|
-
const
|
|
17
|
-
const { device, format } = await createDevice(
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const bindGroups = [] as any[]
|
|
27
|
-
const vertexBuffers = [] as any[]
|
|
28
|
-
const bufferLayouts = [] as any[]
|
|
29
|
-
|
|
30
|
-
const attributes = cached((_, value: number[]) => {
|
|
31
|
-
const { array, buffer } = createVertexBuffer(device, value)
|
|
32
|
-
vertexBuffers.push(buffer)
|
|
33
|
-
bufferLayouts.push(createBufferLayout(bufferLayouts.length, array.length, gl.count))
|
|
34
|
-
state.needsUpdate = true
|
|
35
|
-
return { array, buffer }
|
|
36
|
-
})
|
|
19
|
+
const context = gl.el!.getContext('webgpu') as GPUCanvasContext
|
|
20
|
+
const { device, format } = await createDevice(context)
|
|
21
|
+
const bindings = createBindings()
|
|
22
|
+
let frag: string
|
|
23
|
+
let vert: string
|
|
24
|
+
let flush = (_pass: GPURenderPassEncoder) => {}
|
|
25
|
+
let imageLoading = 0
|
|
26
|
+
let needsUpdate = true
|
|
27
|
+
let depthTexture: GPUTexture
|
|
37
28
|
|
|
38
|
-
const uniforms = cached((
|
|
29
|
+
const uniforms = cached((_key, value: number[]) => {
|
|
30
|
+
needsUpdate = true
|
|
39
31
|
const { array, buffer } = createUniformBuffer(device, value)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return { array, buffer }
|
|
32
|
+
const { binding, group } = bindings.uniform()
|
|
33
|
+
return { binding, group, array, buffer }
|
|
43
34
|
})
|
|
44
35
|
|
|
45
|
-
const textures = cached((
|
|
36
|
+
const textures = cached((_key, width = 0, height = 0) => {
|
|
37
|
+
needsUpdate = true
|
|
46
38
|
const { texture, sampler } = createTextureSampler(device, width, height)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
39
|
+
const { binding, group } = bindings.texture()
|
|
40
|
+
return { binding, group, texture, sampler, view: texture.createView() }
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
const attribs = cached((_key, value: number[]) => {
|
|
44
|
+
needsUpdate = true
|
|
45
|
+
const stride = value.length / gl.count!
|
|
46
|
+
const { location } = bindings.attrib()
|
|
47
|
+
const { array, buffer } = createAttribBuffer(device, value)
|
|
48
|
+
return { array, buffer, location, stride }
|
|
50
49
|
})
|
|
51
50
|
|
|
52
51
|
const update = () => {
|
|
53
|
-
const
|
|
54
|
-
bindGroups
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
52
|
+
const { vertexBuffers, bufferLayouts } = createVertexBuffers(attribs.map.values())
|
|
53
|
+
const { bindGroups, bindGroupLayouts } = createBindGroup(
|
|
54
|
+
device,
|
|
55
|
+
uniforms.map.values(),
|
|
56
|
+
textures.map.values()
|
|
57
|
+
)
|
|
58
|
+
const pipeline = createPipeline(device, format, bufferLayouts, bindGroupLayouts, vert, frag)
|
|
59
|
+
flush = (pass) => {
|
|
60
|
+
pass.setPipeline(pipeline)
|
|
61
|
+
bindGroups.forEach((v, i) => pass.setBindGroup(i, v))
|
|
62
|
+
vertexBuffers.forEach((v, i) => pass.setVertexBuffer(i, v))
|
|
63
|
+
pass.draw(gl.count!, 1, 0, 0)
|
|
64
|
+
pass.end()
|
|
65
|
+
}
|
|
62
66
|
}
|
|
63
67
|
|
|
64
68
|
const render = () => {
|
|
65
|
-
if (
|
|
66
|
-
|
|
67
|
-
|
|
69
|
+
if (!frag || !vert) {
|
|
70
|
+
const config = { isWebGL: false, gl }
|
|
71
|
+
frag = fragment(gl.fs, config)
|
|
72
|
+
vert = vertex(gl.vs, config)
|
|
73
|
+
}
|
|
74
|
+
if (imageLoading) return // MEMO: loading after build node
|
|
75
|
+
if (needsUpdate) update()
|
|
76
|
+
needsUpdate = false
|
|
68
77
|
const encoder = device.createCommandEncoder()
|
|
69
|
-
|
|
70
|
-
pass.setPipeline(state.pipeline)
|
|
71
|
-
bindGroups.forEach((v, i) => pass.setBindGroup(i, v))
|
|
72
|
-
vertexBuffers.forEach((v, i) => pass.setVertexBuffer(i, v))
|
|
73
|
-
pass.draw(gl.count, 1, 0, 0)
|
|
74
|
-
pass.end()
|
|
78
|
+
flush(encoder.beginRenderPass(createDescriptor(context, depthTexture)))
|
|
75
79
|
device.queue.submit([encoder.finish()])
|
|
76
80
|
}
|
|
77
81
|
|
|
78
|
-
const
|
|
82
|
+
const resize = () => {
|
|
83
|
+
const canvas = gl.el as HTMLCanvasElement
|
|
84
|
+
depthTexture?.destroy()
|
|
85
|
+
depthTexture = createDepthTexture(device, canvas.width, canvas.height)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const clean = () => {
|
|
89
|
+
depthTexture?.destroy()
|
|
90
|
+
}
|
|
79
91
|
|
|
80
92
|
const _attribute = (key = '', value: number[]) => {
|
|
81
|
-
const { array, buffer } =
|
|
93
|
+
const { array, buffer } = attribs(key, value)
|
|
94
|
+
array.set(value)
|
|
82
95
|
device.queue.writeBuffer(buffer, 0, array)
|
|
83
96
|
}
|
|
84
97
|
|
|
@@ -90,14 +103,25 @@ export const webgpu = async (gl: Partial<GL>) => {
|
|
|
90
103
|
}
|
|
91
104
|
|
|
92
105
|
const _texture = (key: string, src: string) => {
|
|
93
|
-
|
|
106
|
+
imageLoading++
|
|
94
107
|
const source = Object.assign(new Image(), { src, crossOrigin: 'anonymous' })
|
|
95
108
|
source.decode().then(() => {
|
|
96
|
-
const {
|
|
109
|
+
const { width, height } = source
|
|
110
|
+
const { texture } = textures(key, width, height)
|
|
97
111
|
device.queue.copyExternalImageToTexture({ source }, { texture }, { width, height })
|
|
98
|
-
|
|
112
|
+
imageLoading--
|
|
99
113
|
})
|
|
100
114
|
}
|
|
101
115
|
|
|
102
|
-
|
|
116
|
+
resize()
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
webgpu: { device, uniforms, textures, attribs } as WebGPUState,
|
|
120
|
+
render,
|
|
121
|
+
resize,
|
|
122
|
+
clean,
|
|
123
|
+
_attribute,
|
|
124
|
+
_uniform,
|
|
125
|
+
_texture,
|
|
126
|
+
}
|
|
103
127
|
}
|