glre 0.46.0 → 0.48.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/react.d.ts CHANGED
@@ -69,28 +69,6 @@ declare const OPERATOR_TYPE_RULES: readonly [readonly ["float", "vec2", "vec2"],
69
69
  */
70
70
  declare const FUNCTIONS: readonly [...("texture" | "all" | "any" | "determinant" | "distance" | "dot" | "length" | "lengthSq" | "luminance" | "cross" | "cubeTexture" | "texelFetch" | "textureLod")[], "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh", "ceil", "cos", "cosh", "dFdx", "dFdy", "degrees", "exp", "exp2", "floor", "fract", "fwidth", "inverse", "inverseSqrt", "log", "log2", "negate", "normalize", "oneMinus", "radians", "reciprocal", "round", "sign", "sin", "sinh", "sqrt", "tan", "tanh", "trunc", "saturate", "atan2", "clamp", "max", "min", "mix", "pow", "reflect", "refract", "smoothstep", "step"];
71
71
 
72
- /**
73
- * binding
74
- */
75
- declare const createBinding: () => {
76
- uniform: reev.Nested<{
77
- group: number;
78
- binding: number;
79
- }, []>;
80
- texture: reev.Nested<{
81
- group: number;
82
- binding: number;
83
- }, []>;
84
- storage: reev.Nested<{
85
- group: number;
86
- binding: number;
87
- }, []>;
88
- attrib: reev.Nested<{
89
- location: number;
90
- }, []>;
91
- };
92
- type Binding = ReturnType<typeof createBinding>;
93
-
94
72
  type Constants = (typeof CONSTANTS)[number] | 'void';
95
73
  type Conversions = (typeof CONVERSIONS)[number];
96
74
  type Functions = (typeof FUNCTIONS)[number];
@@ -123,7 +101,6 @@ interface NodeProps {
123
101
  }
124
102
  interface NodeContext {
125
103
  gl?: Partial<GL>;
126
- binding?: Binding;
127
104
  label?: 'vert' | 'frag' | 'compute';
128
105
  isWebGL?: boolean;
129
106
  units?: any;
@@ -408,6 +385,28 @@ interface _X<T extends C> {
408
385
  step<U extends C>(edge: number | X<U>): X<InferOperator<T, U>>;
409
386
  }
410
387
 
388
+ /**
389
+ * binding
390
+ */
391
+ declare const createBinding: () => {
392
+ uniform: reev.Nested<{
393
+ group: number;
394
+ binding: number;
395
+ }, []>;
396
+ texture: reev.Nested<{
397
+ group: number;
398
+ binding: number;
399
+ }, []>;
400
+ storage: reev.Nested<{
401
+ group: number;
402
+ binding: number;
403
+ }, []>;
404
+ attrib: reev.Nested<{
405
+ location: number;
406
+ }, []>;
407
+ };
408
+ type Binding = ReturnType<typeof createBinding>;
409
+
411
410
  type GL = EventState<{
412
411
  /**
413
412
  * initial value
@@ -445,7 +444,9 @@ type GL = EventState<{
445
444
  gpu: GPUCanvasContext;
446
445
  device: GPUDevice;
447
446
  format: GPUTextureFormat;
448
- encoder: GPUCommandEncoder;
447
+ passEncoder: GPURenderPassEncoder;
448
+ commandEncoder: GPUCommandEncoder;
449
+ depthTexture?: GPUTexture;
449
450
  binding: Binding;
450
451
  /**
451
452
  * core state
@@ -499,10 +500,10 @@ type Storage = number[] | Float32Array;
499
500
  * for webgpu
500
501
  */
501
502
  interface UniformData {
502
- array: Float32Array;
503
- buffer: GPUBuffer;
504
503
  binding: number;
505
504
  group: number;
505
+ array: Float32Array;
506
+ buffer: GPUBuffer;
506
507
  }
507
508
  interface TextureData {
508
509
  binding: number;
package/dist/solid.d.ts CHANGED
@@ -69,28 +69,6 @@ declare const OPERATOR_TYPE_RULES: readonly [readonly ["float", "vec2", "vec2"],
69
69
  */
70
70
  declare const FUNCTIONS: readonly [...("texture" | "all" | "any" | "determinant" | "distance" | "dot" | "length" | "lengthSq" | "luminance" | "cross" | "cubeTexture" | "texelFetch" | "textureLod")[], "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh", "ceil", "cos", "cosh", "dFdx", "dFdy", "degrees", "exp", "exp2", "floor", "fract", "fwidth", "inverse", "inverseSqrt", "log", "log2", "negate", "normalize", "oneMinus", "radians", "reciprocal", "round", "sign", "sin", "sinh", "sqrt", "tan", "tanh", "trunc", "saturate", "atan2", "clamp", "max", "min", "mix", "pow", "reflect", "refract", "smoothstep", "step"];
71
71
 
72
- /**
73
- * binding
74
- */
75
- declare const createBinding: () => {
76
- uniform: reev.Nested<{
77
- group: number;
78
- binding: number;
79
- }, []>;
80
- texture: reev.Nested<{
81
- group: number;
82
- binding: number;
83
- }, []>;
84
- storage: reev.Nested<{
85
- group: number;
86
- binding: number;
87
- }, []>;
88
- attrib: reev.Nested<{
89
- location: number;
90
- }, []>;
91
- };
92
- type Binding = ReturnType<typeof createBinding>;
93
-
94
72
  type Constants = (typeof CONSTANTS)[number] | 'void';
95
73
  type Conversions = (typeof CONVERSIONS)[number];
96
74
  type Functions = (typeof FUNCTIONS)[number];
@@ -123,7 +101,6 @@ interface NodeProps {
123
101
  }
124
102
  interface NodeContext {
125
103
  gl?: Partial<GL>;
126
- binding?: Binding;
127
104
  label?: 'vert' | 'frag' | 'compute';
128
105
  isWebGL?: boolean;
129
106
  units?: any;
@@ -408,6 +385,28 @@ interface _X<T extends C> {
408
385
  step<U extends C>(edge: number | X<U>): X<InferOperator<T, U>>;
409
386
  }
410
387
 
388
+ /**
389
+ * binding
390
+ */
391
+ declare const createBinding: () => {
392
+ uniform: reev.Nested<{
393
+ group: number;
394
+ binding: number;
395
+ }, []>;
396
+ texture: reev.Nested<{
397
+ group: number;
398
+ binding: number;
399
+ }, []>;
400
+ storage: reev.Nested<{
401
+ group: number;
402
+ binding: number;
403
+ }, []>;
404
+ attrib: reev.Nested<{
405
+ location: number;
406
+ }, []>;
407
+ };
408
+ type Binding = ReturnType<typeof createBinding>;
409
+
411
410
  type GL = EventState<{
412
411
  /**
413
412
  * initial value
@@ -445,7 +444,9 @@ type GL = EventState<{
445
444
  gpu: GPUCanvasContext;
446
445
  device: GPUDevice;
447
446
  format: GPUTextureFormat;
448
- encoder: GPUCommandEncoder;
447
+ passEncoder: GPURenderPassEncoder;
448
+ commandEncoder: GPUCommandEncoder;
449
+ depthTexture?: GPUTexture;
449
450
  binding: Binding;
450
451
  /**
451
452
  * core state
@@ -499,10 +500,10 @@ type Storage = number[] | Float32Array;
499
500
  * for webgpu
500
501
  */
501
502
  interface UniformData {
502
- array: Float32Array;
503
- buffer: GPUBuffer;
504
503
  binding: number;
505
504
  group: number;
505
+ array: Float32Array;
506
+ buffer: GPUBuffer;
506
507
  }
507
508
  interface TextureData {
508
509
  binding: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "glre",
3
- "version": "0.46.0",
3
+ "version": "0.48.0",
4
4
  "author": "tseijp",
5
5
  "license": "MIT",
6
6
  "private": false,
package/src/helpers.ts CHANGED
@@ -64,9 +64,9 @@ const calcStride = (arrayLength: number, count = 3) => {
64
64
  return -1
65
65
  }
66
66
 
67
- export const getStride = (arrayLength: number, count = 1, error = console.warn) => {
67
+ export const getStride = (arrayLength: number, count = 1, error = console.warn, id = '') => {
68
68
  const ret = calcStride(arrayLength, count)
69
- if (!isValidStride(ret)) error(`glre attribute error: Invalid attribute length ${arrayLength}. Must divide by vertex count (${count}) with valid stride (1,2,3,4,9,16)`)
69
+ if (!isValidStride(ret)) error(`glre attribute error: Invalid attribute length ${arrayLength}, ${id ? `${id} ` : ' '}must divide by vertex count (${count}) with valid stride (1,2,3,4,9,16)`)
70
70
  return ret
71
71
  }
72
72
 
package/src/index.ts CHANGED
@@ -55,17 +55,19 @@ export const createGL = (...args: Partial<GL>[]) => {
55
55
  gl.el = findElement(gl) || el || args.map(findElement).find(Boolean)
56
56
  const isAppend = !gl.el // Check first: canvas may unmount during WebGPU async processing
57
57
  if (isAppend && !gl.isNative) gl.el = document.createElement('canvas')
58
- for (const arg of args) {
58
+ for (let i = 0; i < args.length; i++) {
59
+ const arg = args[i]
59
60
  gl.fs = arg.fs || arg.frag || arg.fragment || undefined
60
61
  gl.cs = arg.cs || arg.comp || arg.compute || undefined
61
62
  gl.vs = arg.vs || arg.vert || arg.vertex || undefined
62
- gl.triangleCount = arg.triangleCount || arg.count || 6
63
+ gl.triangleCount = arg.triangleCount || 2
63
64
  gl.instanceCount = arg.instanceCount || 1
64
65
  gl.particleCount = arg.particleCount || 1024
66
+ gl.count = arg.count || gl.triangleCount * 3 || 6
65
67
  gl(arg)
66
68
  if (is.bol(arg.isWebGL)) gl.isWebGL = arg.isWebGL || !isWebGPUSupported()
67
69
  if (gl.isWebGL) webgl(gl)
68
- else await webgpu(gl)
70
+ else await webgpu(gl, i === args.length - 1)
69
71
  if (arg.mount) arg.mount() // events added in mount phase need explicit call to execute
70
72
  }
71
73
  if (!gl.el || gl.isError) return // stop if error or canvas was unmounted during async
package/src/node/types.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { CONSTANTS, CONVERSIONS, FUNCTIONS, OPERATOR_KEYS, OPERATOR_TYPE_RULES } from './utils/const'
2
2
  import type { GL } from '../types'
3
- import type { Binding } from '../webgpu/utils'
4
3
 
5
4
  export type Constants = (typeof CONSTANTS)[number] | 'void'
6
5
  export type Conversions = (typeof CONVERSIONS)[number]
@@ -81,7 +80,6 @@ export interface NodeProps {
81
80
 
82
81
  export interface NodeContext {
83
82
  gl?: Partial<GL>
84
- binding?: Binding
85
83
  label?: 'vert' | 'frag' | 'compute'
86
84
  isWebGL?: boolean
87
85
  units?: any // @TODO FIX
@@ -114,7 +114,10 @@ export const code = <T extends C>(target: Y<T>, c?: NodeContext | null): string
114
114
  setupEvent(c, id, varType, target, x)
115
115
  head = parseUniformHead(c, id, varType)
116
116
  }
117
- if (type === 'storage') head = parseStorageHead(c, id, infer(target, c))
117
+ if (type === 'storage') {
118
+ setupEvent(c, id, type, target, x)
119
+ head = parseStorageHead(c, id, infer(target, c))
120
+ }
118
121
  if (type === 'constant') head = parseConstantHead(c, id, infer(target, c), code(x, c))
119
122
  if (head) {
120
123
  c.code?.headers.set(id, head)
@@ -1,6 +1,6 @@
1
1
  import { isConstants, isElement, isX, isSwizzle } from './utils'
2
2
  import { BUILTIN_TYPES, COMPONENT_COUNT_TO_TYPE, FUNCTION_RETURN_TYPES, getOperatorResultType, validateOperatorTypes } from './const'
3
- import { is, getStride } from '../../helpers'
3
+ import { is, getStride, isFloat32 } from '../../helpers'
4
4
  import type { Constants as C, NodeContext, X, Y } from '../types'
5
5
 
6
6
  const inferBuiltin = <T extends C>(id: string | undefined) => {
@@ -16,14 +16,14 @@ export const inferPrimitiveType = <T extends C>(x: Y<T>) => {
16
16
  if (is.bol(x)) return 'bool' as T
17
17
  if (is.str(x)) return 'texture' as T
18
18
  if (is.num(x)) return 'float' as T // @TODO FIX: Number.isInteger(x) ? 'int' : 'float'
19
- if (is.arr(x)) return COMPONENT_COUNT_TO_TYPE[x.length as keyof typeof COMPONENT_COUNT_TO_TYPE] as T
19
+ if (is.arr(x) || isFloat32(x)) return COMPONENT_COUNT_TO_TYPE[x.length as keyof typeof COMPONENT_COUNT_TO_TYPE] as T
20
20
  if (isElement(x)) return 'texture' as T
21
21
  return 'void' as T
22
22
  }
23
23
 
24
- const inferFromCount = <T extends C>(count: number) => {
24
+ const inferFromCount = <T extends C>(count: number, error = console.warn, id = '') => {
25
25
  const ret = COMPONENT_COUNT_TO_TYPE[count as keyof typeof COMPONENT_COUNT_TO_TYPE] as T
26
- if (!ret) throw `glre node system error: Cannot infer type from array length ${count}. Check your data size. Supported: 1(float), 2(vec2), 3(vec3), 4(vec4), 9(mat3), 16(mat4)`
26
+ if (!ret) console.warn(`glre node system error: Cannot infer ${id ? `${id} ` : ''} type from array length ${count}. Check your data size. Supported: 1(float), 2(vec2), 3(vec3), 4(vec4), 9(mat3), 16(mat4)`)
27
27
  return ret
28
28
  }
29
29
 
@@ -54,16 +54,15 @@ export const inferImpl = <T extends C>(target: X<T>, c: NodeContext): T => {
54
54
  if (!inferFrom || inferFrom.length === 0) return 'void' as T
55
55
  return inferFromArray(inferFrom, c)
56
56
  }
57
- if (type === 'attribute' && is.arr(x)) {
58
- const stride = getStride(x.length, c.gl?.count, c.gl?.error)
59
- return inferFromCount(stride)
60
- }
61
- if (type === 'instance' && is.arr(x)) {
62
- const stride = getStride(x.length, c.gl?.instanceCount, c.gl?.error)
63
- return inferFromCount(stride)
64
- }
57
+ if (type === 'attribute' || type === 'instance')
58
+ if (is.arr(x)) {
59
+ const count = type === 'instance' ? c.gl?.instanceCount : c.gl?.count
60
+ const stride = getStride(x.length, count, c.gl?.error, id)
61
+ return inferFromCount(stride, c.gl?.error, id)
62
+ }
63
+
65
64
  if (type === 'member') {
66
- if (isSwizzle(y)) return inferFromCount(y.length)
65
+ if (isSwizzle(y)) return inferFromCount(y.length, c.gl?.error, id)
67
66
  if (isX(x)) {
68
67
  const structType = infer(x, c)
69
68
  const fields = c.code?.structStructFields?.get(structType)
@@ -78,7 +77,7 @@ export const inferImpl = <T extends C>(target: X<T>, c: NodeContext): T => {
78
77
  export const infer = <T extends C>(target: Y<T>, c?: NodeContext | null): T => {
79
78
  if (!c) c = {}
80
79
  if (!isX(target)) return inferPrimitiveType(target)
81
- if (is.arr(target)) return inferFromCount(target.length)
80
+ if (is.arr(target)) return inferFromCount(target.length, c.gl?.error, target.props.id)
82
81
  if (!c.infers) c.infers = new WeakMap<X<T>, C>()
83
82
  if (c.infers.has(target)) return c.infers.get(target) as T
84
83
  const ret = inferImpl(target, c)
@@ -2,8 +2,8 @@ import { code } from '.'
2
2
  import { infer } from './infer'
3
3
  import { getConversions, addDependency } from './utils'
4
4
  import { is } from '../../helpers'
5
- import type { Constants, NodeContext, NodeProps, StructFields, Y } from '../types'
6
5
  import { storageSize } from '../../webgl/utils'
6
+ import type { Constants, NodeContext, NodeProps, StructFields, Y } from '../types'
7
7
 
8
8
  export const parseArray = (children: Y[], c: NodeContext) => {
9
9
  return children
@@ -159,7 +159,7 @@ export const parseVaryingHead = (c: NodeContext, id: string, type: Constants) =>
159
159
 
160
160
  export const parseAttribHead = (c: NodeContext, id: string, type: Constants) => {
161
161
  if (c.isWebGL) return `${type} ${id};`
162
- const { location = 0 } = c.binding?.attrib(id) || {}
162
+ const { location = 0 } = c.gl?.binding?.attrib(id) || {}
163
163
  const wgslType = getConversions(type, c)
164
164
  return `@location(${location}) ${id}: ${wgslType}`
165
165
  }
@@ -171,10 +171,10 @@ export const parseUniformHead = (c: NodeContext, id: string, type: Constants) =>
171
171
  ? `uniform sampler2D ${id};`
172
172
  : `uniform ${type} ${id};`
173
173
  if (isTexture) {
174
- const { group = 1, binding = 0 } = c.binding?.texture(id) || {}
174
+ const { group = 1, binding = 0 } = c.gl?.binding?.texture(id) || {}
175
175
  return `@group(${group}) @binding(${binding}) var ${id}Sampler: sampler;\n` + `@group(${group}) @binding(${binding + 1}) var ${id}: texture_2d<f32>;`
176
176
  }
177
- const { group = 0, binding = 0 } = c.binding?.uniform(id) || {}
177
+ const { group = 0, binding = 0 } = c.gl?.binding?.uniform(id) || {}
178
178
  const wgslType = getConversions(type, c)
179
179
  return `@group(${group}) @binding(${binding}) var<uniform> ${id}: ${wgslType};`
180
180
  }
@@ -186,7 +186,7 @@ export const parseStorageHead = (c: NodeContext, id: string, type: Constants) =>
186
186
  const location = c.units?.(id)
187
187
  return `${ret}\nlayout(location = ${location}) out vec4 _${id};` // out texture buffer
188
188
  }
189
- const { group = 0, binding = 0 } = c.binding?.storage(id) || {}
189
+ const { group = 0, binding = 0 } = c.gl?.binding?.storage(id) || {}
190
190
  const wgslType = getConversions(type, c)
191
191
  return `@group(${group}) @binding(${binding}) var<storage, read_write> ${id}: array<${wgslType}>;`
192
192
  }
@@ -1,5 +1,5 @@
1
1
  import { CONSTANTS, CONVERSIONS, FUNCTIONS, OPERATOR_KEYS, OPERATORS, TYPE_MAPPING, WGSL_TO_GLSL_BUILTIN } from './const'
2
- import { is } from '../../helpers'
2
+ import { is, isFloat32 } from '../../helpers'
3
3
  import { storageSize } from '../../webgl/utils'
4
4
  import type { Constants as C, Conversions, Functions, NodeContext, Operators, Swizzles, X, Y } from '../types'
5
5
 
@@ -103,28 +103,33 @@ export const addDependency = (c: NodeContext, id = '', type: string) => {
103
103
  */
104
104
  const getEventFun = (c: NodeContext, id: string, type: string) => {
105
105
  if (c.isWebGL) {
106
- if (type === 'attribute') return (value: any) => c.gl?.attribute?.(id, value)
107
- if (type === 'instance') return (value: any) => c.gl?.instance?.(id, value)
108
- if (type === 'texture') return (value: any) => c.gl?.texture?.(id, value)
106
+ if (type === 'attribute') return c.gl?.attribute?.bind(null, id as any)
107
+ if (type === 'instance') return c.gl?.instance?.bind(null, id as any)
108
+ if (type === 'texture') return c.gl?.texture?.bind(null, id as any)
109
+ if (type === 'storage') return c.gl?.storage?.bind(null, id as any)
109
110
  return (value: any) => c.gl?.uniform?.(id, value)
110
111
  }
111
- if (type === 'attribute') return (value: any) => c.gl?._attribute?.(id, value)
112
- if (type === 'instance') return (value: any) => c.gl?._instance?.(id, value)
113
- if (type === 'texture') return (value: any) => c.gl?._texture?.(id, value)
112
+ if (type === 'attribute') return c.gl?._attribute?.bind(null, id)
113
+ if (type === 'instance') return c.gl?._instance?.bind(null, id)
114
+ if (type === 'texture') return c.gl?._texture?.bind(null, id)
115
+ if (type === 'storage') return c.gl?._storage?.bind(null, id)
114
116
  return (value: any) => c.gl?._uniform?.(id, value)
115
117
  }
116
118
 
117
- const safeEventCall = <T extends C>(x: X<T>, fun: (value: unknown) => void) => {
119
+ const safeEventCall = <T extends C>(x: X<T>, fun: (value: any) => void) => {
118
120
  if (is.und(x)) return
119
121
  if (!isX(x)) return fun(x) // for uniform(0) or uniform([0, 1])
120
122
  if (x.type !== 'conversion') return
121
123
  const args = x.props.children?.slice(1)
122
124
  if (is.und(args?.[0])) return // ignore if uniform(vec2())
125
+ if (is.arr(args[0])) return fun(args[0]) // for attribute(vec2([0, 0.73, -1, -1, 1, -1]))
126
+ if (isFloat32(args[0])) return fun(args[0]) // for storage(float(new Float32Array(1024)))
123
127
  fun(args.map((x) => x ?? args[0])) // for uniform(vec2(1)) or uniform(vec2(1, 1))
124
128
  }
125
129
 
126
130
  export const setupEvent = (c: NodeContext, id: string, type: string, target: X, child: X) => {
127
131
  const fun = getEventFun(c, id, type)
132
+ if (!fun) return
128
133
  safeEventCall(child, fun)
129
134
  target.listeners.add(fun)
130
135
  return fun
package/src/types.ts CHANGED
@@ -18,7 +18,7 @@ export type GL = EventState<{
18
18
  height?: number
19
19
  size: [number, number]
20
20
  mouse: [number, number]
21
- count: number
21
+ count: number // triangleCount × 3
22
22
  triangleCount: number
23
23
  instanceCount: number
24
24
  particleCount: number | [number, number] | [number, number, number]
@@ -40,7 +40,9 @@ export type GL = EventState<{
40
40
  gpu: GPUCanvasContext
41
41
  device: GPUDevice
42
42
  format: GPUTextureFormat
43
- encoder: GPUCommandEncoder
43
+ passEncoder: GPURenderPassEncoder
44
+ commandEncoder: GPUCommandEncoder
45
+ depthTexture?: GPUTexture
44
46
  binding: Binding
45
47
 
46
48
  /**
@@ -91,10 +93,10 @@ type Storage = number[] | Float32Array
91
93
  * for webgpu
92
94
  */
93
95
  export interface UniformData {
94
- array: Float32Array
95
- buffer: GPUBuffer
96
96
  binding: number
97
97
  group: number
98
+ array: Float32Array
99
+ buffer: GPUBuffer
98
100
  }
99
101
 
100
102
  export interface TextureData {
@@ -4,17 +4,17 @@ import { GLSL_VS, is } from '../helpers'
4
4
  import type { GL } from '../types'
5
5
 
6
6
  export const compute = (gl: GL) => {
7
- if (!gl.cs) return
8
- const c = gl.gl
7
+ let { cs, particleCount, gl: c } = gl
8
+ if (!cs) return
9
9
  c.getExtension('EXT_color_buffer_float') // Enable high precision GPGPU by writing to float textures
10
10
 
11
11
  let _texture = 0 // for texture active units
12
12
  let _storage = 0 // for storage current num
13
13
 
14
14
  const units = nested(() => _texture++)
15
- const cs = is.str(gl.cs) ? gl.cs : gl.cs!.compute({ isWebGL: true, gl, units })
15
+ cs = is.str(cs) ? cs : cs!.compute({ isWebGL: true, gl, units })
16
16
  const pg = createProgram(c, cs, GLSL_VS, gl)!
17
- const size = storageSize(gl.particleCount)
17
+ const size = storageSize(particleCount)
18
18
 
19
19
  const uniforms = nested((key) => c.getUniformLocation(pg, key)!)
20
20
  const storages = nested((key) => {
@@ -4,17 +4,17 @@ import { createBuffer, createProgram, createTexture, updateAttrib, updateBuffer,
4
4
  import type { GL } from '../types'
5
5
 
6
6
  export const graphic = (gl: GL) => {
7
+ let { fs, vs, gl: c } = gl // @TODO Save this WebGPU instance's count (overwritten per args) but no change now for top page
7
8
  const config = { isWebGL: true, gl }
8
- const c = gl.gl
9
- const fs = gl.fs ? (is.str(gl.fs) ? gl.fs : gl.fs.fragment(config)) : GLSL_FS
10
- const vs = gl.vs ? (is.str(gl.vs) ? gl.vs : gl.vs.vertex(config)) : GLSL_VS
9
+ fs = gl.fs ? (is.str(gl.fs) ? gl.fs : gl.fs.fragment(config)) : GLSL_FS
10
+ vs = gl.vs ? (is.str(gl.vs) ? gl.vs : gl.vs.vertex(config)) : GLSL_VS
11
11
  const pg = createProgram(c, fs, vs, gl)!
12
12
  let activeUnit = 0
13
13
 
14
14
  const units = nested(() => activeUnit++)
15
15
  const uniforms = nested((key) => c.getUniformLocation(pg, key))
16
16
  const attributes = nested((key, value: number[], isInstance = false) => {
17
- const stride = getStride(value.length, isInstance ? gl.instanceCount : gl.triangleCount, gl.error)
17
+ const stride = getStride(value.length, isInstance ? gl.instanceCount : gl.count, gl.error, key)
18
18
  return { stride, location: c.getAttribLocation(pg, key), ...createBuffer(c, value) }
19
19
  })
20
20
 
@@ -56,8 +56,8 @@ export const graphic = (gl: GL) => {
56
56
  gl('render', () => {
57
57
  c.useProgram((gl.program = pg))
58
58
  if (gl.instanceCount > 1) {
59
- c.drawArraysInstanced(c.TRIANGLES, 0, gl.triangleCount, gl.instanceCount)
60
- } else c.drawArrays(c.TRIANGLES, 0, gl.triangleCount)
59
+ c.drawArraysInstanced(c.TRIANGLES, 0, gl.count, gl.instanceCount)
60
+ } else c.drawArrays(c.TRIANGLES, 0, gl.count)
61
61
  c.bindFramebuffer(c.FRAMEBUFFER, null)
62
62
  })
63
63
  }
@@ -1,14 +1,14 @@
1
1
  import { nested } from 'reev'
2
2
  import { createBuffer, updateBuffer, workgroupCount } from './utils'
3
- import type { Binding } from './utils'
4
3
  import type { GL } from '../types'
5
4
 
6
- export const compute = (gl: GL, bindings: Binding) => {
5
+ export const compute = (gl: GL) => {
6
+ const { particleCount } = gl // Save this WebGPU instance's particleCount (overwritten per args)
7
7
  let pipeline: GPUComputePipeline | undefined
8
8
  let bindGroups: GPUBindGroup[] | undefined
9
9
 
10
10
  const storages = nested((key, value: number[] | Float32Array) => {
11
- return { ...bindings.storage(key), ...createBuffer(gl.device, value, 'storage') }
11
+ return { ...gl.binding.storage(key), ...createBuffer(gl.device, value, 'storage') }
12
12
  })
13
13
 
14
14
  gl('_storage', (key: string, value: number[] | Float32Array) => {
@@ -18,10 +18,10 @@ export const compute = (gl: GL, bindings: Binding) => {
18
18
 
19
19
  gl('render', () => {
20
20
  if (!pipeline || !bindGroups) return
21
- const pass = gl.encoder.beginComputePass()
21
+ const pass = gl.commandEncoder.beginComputePass()
22
22
  pass.setPipeline(pipeline)
23
23
  bindGroups.forEach((v, i) => pass.setBindGroup(i, v))
24
- const { x, y, z } = workgroupCount(gl.particleCount)
24
+ const { x, y, z } = workgroupCount(particleCount)
25
25
  pass.dispatchWorkgroups(x, y, z)
26
26
  pass.end()
27
27
  })
@@ -1,28 +1,27 @@
1
1
  import { nested } from 'reev'
2
- import { is, getStride, loadingTexture } from '../helpers'
3
- import { createBuffer, createDepthTexture, createDescriptor, createTextureSampler, updateBuffer } from './utils'
4
- import type { Binding } from './utils'
2
+ import { getStride, is, loadingTexture } from '../helpers'
3
+ import { createBuffer, createTextureSampler, updateBuffer } from './utils'
5
4
  import type { GL } from '../types'
6
5
 
7
- export const graphic = (gl: GL, bindings: Binding, update = () => {}) => {
6
+ export const graphic = (gl: GL, update = () => {}) => {
7
+ const { count, instanceCount } = gl // // Save this WebGPU item's count (overwritten per args)
8
8
  let pipeline: GPURenderPipeline
9
9
  let bindGroups: GPUBindGroup[]
10
10
  let vertexBuffers: GPUBuffer[]
11
- let depthTexture: GPUTexture
12
11
 
13
- const attributes = nested((key, value: number[], isInstance = false, stride = getStride(value.length, isInstance ? gl.instanceCount : gl.triangleCount)) => {
12
+ const attributes = nested((key, value: number[], isInstance = false, stride = getStride(value.length, isInstance ? instanceCount : count, gl.error, key)) => {
14
13
  update()
15
- return { ...bindings.attrib(key), ...createBuffer(gl.device, value, 'attrib'), isInstance, stride }
14
+ return { ...gl.binding.attrib(key), ...createBuffer(gl.device, value, 'attrib'), isInstance, stride }
16
15
  })
17
16
 
18
17
  const uniforms = nested((key, value: number[] | Float32Array) => {
19
18
  update()
20
- return { ...bindings.uniform(key), ...createBuffer(gl.device, value, 'uniform') }
19
+ return { ...gl.binding.uniform(key), ...createBuffer(gl.device, value, 'uniform') }
21
20
  })
22
21
 
23
22
  const textures = nested((key, width = 1, height = 1) => {
24
23
  update()
25
- return { ...bindings.texture(key), ...createTextureSampler(gl.device, width, height) }
24
+ return { ...gl.binding.texture(key), ...createTextureSampler(gl.device, width, height) }
26
25
  })
27
26
 
28
27
  gl('_attribute', (key: string, value: number[] | Float32Array) => {
@@ -45,11 +44,9 @@ export const graphic = (gl: GL, bindings: Binding, update = () => {}) => {
45
44
  const t = textures(key)
46
45
  loadingTexture(src, (source, isVideo) => {
47
46
  const [width, height] = isVideo ? [source.videoWidth, source.videoHeight] : [source.width, source.height]
48
- if (t.texture.width !== width || t.texture.height !== height) {
49
- t.texture.destroy()
50
- Object.assign(t, createTextureSampler(gl.device, width, height))
51
- update() // Rebuilding BindGroups because the texture size has changed
52
- }
47
+ t.texture.destroy()
48
+ Object.assign(t, createTextureSampler(gl.device, width, height))
49
+ update() // Rebuilding BindGroups because the texture size has changed
53
50
  const render = () => void gl.device.queue.copyExternalImageToTexture({ source }, { texture: t.texture }, { width, height })
54
51
  if (isVideo) gl({ render })
55
52
  else render()
@@ -58,22 +55,13 @@ export const graphic = (gl: GL, bindings: Binding, update = () => {}) => {
58
55
 
59
56
  gl('render', () => {
60
57
  if (!pipeline || !bindGroups || !vertexBuffers) return
61
- const pass = gl.encoder.beginRenderPass(createDescriptor(gl.gpu, depthTexture))
62
- pass.setPipeline(pipeline)
63
- bindGroups.forEach((v, i) => pass.setBindGroup(i, v))
64
- vertexBuffers.forEach((v, i) => pass.setVertexBuffer(i, v))
65
- pass.draw(gl.triangleCount, gl.instanceCount, 0, 0)
66
- pass.end()
67
- })
68
-
69
- gl('resize', () => {
70
- const canvas = gl.el as HTMLCanvasElement
71
- depthTexture?.destroy()
72
- depthTexture = createDepthTexture(gl.device, canvas.width, canvas.height)
58
+ gl.passEncoder.setPipeline(pipeline)
59
+ bindGroups.forEach((v, i) => gl.passEncoder.setBindGroup(i, v))
60
+ vertexBuffers.forEach((v, i) => gl.passEncoder.setVertexBuffer(i, v))
61
+ gl.passEncoder.draw(count, instanceCount, 0, 0)
73
62
  })
74
63
 
75
64
  gl('clean', () => {
76
- depthTexture?.destroy()
77
65
  for (const { buffer } of attributes.map.values()) buffer.destroy()
78
66
  for (const { texture } of textures.map.values()) texture.destroy()
79
67
  for (const { buffer } of uniforms.map.values()) buffer.destroy()