glre 0.31.0 → 0.32.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/src/node/scope.ts CHANGED
@@ -3,24 +3,22 @@ import { conversion, node } from './node'
3
3
  import { getId } from './utils'
4
4
  import type { FnLayout, NodeProps, NodeProxy, X } from './types'
5
5
 
6
- let _scope: NodeProxy | null = null
7
-
8
- const scoped = (x: NodeProxy | null, fun = () => {}) => {
9
- const prev = _scope
10
- _scope = x
11
- fun()
12
- _scope = prev
13
- }
6
+ let scope: NodeProxy | null = null
7
+ let define: NodeProxy | null = null
14
8
 
15
9
  const addToScope = (x: NodeProxy) => {
16
- if (!_scope) return // ignore
17
- if (!_scope.props.children) _scope.props.children = []
18
- _scope.props.children.push(x)
10
+ if (!scope) return
11
+ if (!scope.props.children) scope.props.children = []
12
+ scope.props.children.push(x)
13
+ if (x.type !== 'return' || !define) return
14
+ const { props } = define
15
+ if (!props.inferFrom) props.inferFrom = []
16
+ props.inferFrom.push(x)
19
17
  }
20
18
 
21
19
  export const toVar = (x: X, id?: string) => {
22
20
  if (!id) id = getId()
23
- const y = node('variable', { id, inferFrom: x })
21
+ const y = node('variable', { id, inferFrom: [x] })
24
22
  const z = node('declare', null, x, y)
25
23
  addToScope(z)
26
24
  return y
@@ -32,6 +30,27 @@ export const assign = (x: X, y: X) => {
32
30
  return x
33
31
  }
34
32
 
33
+ export const Return = (x: X) => {
34
+ const y = node('return', { inferFrom: [x] }, x)
35
+ addToScope(y)
36
+ return y
37
+ }
38
+
39
+ const scoped = (x: NodeProxy, fun: () => NodeProxy | void, y = define) => {
40
+ // cache to revert
41
+ const _scope = scope
42
+ const _define = define
43
+ // update
44
+ scope = x
45
+ define = y
46
+ if (_scope) x.props.parent = _scope
47
+ const z = fun()
48
+ if (z) Return(z)
49
+ // revert
50
+ scope = _scope
51
+ define = _define
52
+ }
53
+
35
54
  export const If = (x: X, fun: () => void) => {
36
55
  const y = node('scope')
37
56
  scoped(y, fun)
@@ -55,7 +74,7 @@ export const If = (x: X, fun: () => void) => {
55
74
 
56
75
  export const Loop = (x: X, fun: (params: { i: NodeProxy }) => void) => {
57
76
  const y = node('scope')
58
- scoped(y, () => fun({ i: node('variable', { id: 'i', inferFrom: int(0) }) }))
77
+ scoped(y, () => fun({ i: node('variable', { id: 'i', inferFrom: [int(0)] }) }))
59
78
  const ret = node('loop', null, x, y)
60
79
  addToScope(ret)
61
80
  return ret
@@ -88,20 +107,20 @@ export const Fn = (fun: (paramVars: NodeProxy[]) => NodeProxy) => {
88
107
  const ret = (...args: X[]) => {
89
108
  const id = layout?.name || getId()
90
109
  const x = node('scope')
91
- let y: NodeProxy | undefined
92
110
  const paramVars: NodeProxy[] = []
93
111
  const paramDefs: NodeProps[] = []
94
112
  if (layout?.inputs)
95
113
  for (const input of layout.inputs) {
96
- paramDefs.push({ id: input.name, inferFrom: conversion(input.type) })
114
+ paramDefs.push({ id: input.name, inferFrom: [conversion(input.type)] })
97
115
  }
98
116
  else
99
117
  for (let i = 0; i < args.length; i++) {
100
- paramDefs.push({ id: `p${i}`, inferFrom: args[i] })
118
+ paramDefs.push({ id: `p${i}`, inferFrom: [args[i]] })
101
119
  }
102
120
  for (const props of paramDefs) paramVars.push(node('variable', props))
103
- scoped(x, () => (y = fun(paramVars)))
104
- return node('define', { id, layout }, x, y, ...args)
121
+ const y = node('define', { id, layout }, x, ...args)
122
+ scoped(x, () => fun(paramVars), y)
123
+ return y
105
124
  }
106
125
  ret.setLayout = (newLayout: FnLayout) => {
107
126
  layout = newLayout
package/src/node/types.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { WebGPUState } from '../types'
1
2
  import { CONSTANTS, CONVERSIONS, FUNCTIONS, OPERATOR_KEYS } from './const'
2
3
 
3
4
  export type Constants = (typeof CONSTANTS)[number] | 'void'
@@ -17,23 +18,60 @@ export interface FnLayout {
17
18
  }>
18
19
  }
19
20
 
21
+ /**
22
+ * Node
23
+ */
24
+ export type NodeTypes =
25
+ // headers
26
+ | 'attribute'
27
+ | 'uniform'
28
+ | 'constant'
29
+ // variables
30
+ | 'variable'
31
+ | 'varying'
32
+ | 'swizzle'
33
+ | 'ternary'
34
+ | 'builtin'
35
+ | 'conversion'
36
+ | 'operator'
37
+ | 'function'
38
+ // scopes
39
+ | 'scope'
40
+ | 'assign'
41
+ | 'loop'
42
+ | 'define'
43
+ | 'if'
44
+ | 'switch'
45
+ | 'declare'
46
+ | 'return'
47
+
20
48
  export interface NodeProps {
21
49
  id?: string
22
50
  args?: X[]
23
51
  type?: string
24
52
  children?: X[]
25
- inferFrom?: X
53
+ inferFrom?: X[]
26
54
  layout?: FnLayout
55
+ parent?: NodeProxy
27
56
  }
28
57
 
29
- export interface NodeConfig {
58
+ export interface NodeContext {
59
+ isFrag?: boolean
30
60
  isWebGL?: boolean
31
61
  binding?: number
32
62
  infers?: WeakMap<NodeProxy, Constants>
33
- headers?: Map<string, string>
34
63
  onMount?: (name: string) => void
64
+ webgpu?: WebGPUState
65
+ headers?: Map<string, string>
66
+ fragInputs?: Map<string, string>
67
+ vertInputs?: Map<string, string>
68
+ vertOutputs?: Map<string, string>
69
+ vertVaryings?: Map<string, string>
35
70
  }
36
71
 
72
+ /**
73
+ * NodeProxy
74
+ */
37
75
  type _Swizzles<T extends string> = T | `${T}${T}` | `${T}${T}${T}` | `${T}${T}${T}${T}`
38
76
 
39
77
  export type Swizzles =
@@ -42,31 +80,33 @@ export type Swizzles =
42
80
  | _Swizzles<'p' | 'q'>
43
81
  | _Swizzles<'s' | 't'>
44
82
 
45
- export type NodeTypes =
46
- // headers
47
- | 'attribute'
48
- | 'uniform'
49
- | 'varying'
50
- | 'constant'
51
- // variables
52
- | 'variable'
53
- | 'swizzle'
54
- | 'ternary'
55
- | 'builtin'
56
- | 'conversion'
57
- | 'operator'
58
- | 'function'
59
- // scopes
60
- | 'scope'
83
+ type NodeProxyMethods =
84
+ | Functions
85
+ | Operators
86
+ | Conversions
87
+ | Swizzles
88
+ // system property
89
+ | 'type'
90
+ | 'props'
91
+ | 'isProxy'
61
92
  | 'assign'
62
- | 'loop'
63
- | 'define'
64
- | 'if'
65
- | 'switch'
66
- | 'declare'
93
+ | 'toVar'
94
+ | 'toString'
67
95
 
68
- export interface NodeProxy extends Record<Swizzles, NodeProxy> {
69
- // Operators
96
+ export type DynamicProperties = {
97
+ [K in string as K extends NodeProxyMethods ? never : K]: NodeProxy
98
+ }
99
+
100
+ export interface BaseNodeProxy extends Record<Swizzles, NodeProxy> {
101
+ // System properties
102
+ assign(n: X): NodeProxy
103
+ toVar(name?: string): NodeProxy
104
+ toString(c?: NodeContext): string
105
+ type: NodeTypes
106
+ props: NodeProps
107
+ isProxy: true
108
+
109
+ // Operators methods
70
110
  add(n: X): NodeProxy
71
111
  sub(n: X): NodeProxy
72
112
  mul(n: X): NodeProxy
@@ -82,11 +122,29 @@ export interface NodeProxy extends Record<Swizzles, NodeProxy> {
82
122
  or(n: X): NodeProxy
83
123
  not(): NodeProxy
84
124
 
85
- // Variable manipulation
86
- assign(n: X): NodeProxy
87
- toVar(name?: string): NodeProxy
125
+ // Conversations methods
126
+ toBool(): NodeProxy
127
+ toUint(): NodeProxy
128
+ toInt(): NodeProxy
129
+ toFloat(): NodeProxy
130
+ toBvec2(): NodeProxy
131
+ toIvec2(): NodeProxy
132
+ toUvec2(): NodeProxy
133
+ toVec2(): NodeProxy
134
+ toBvec3(): NodeProxy
135
+ toIvec3(): NodeProxy
136
+ toUvec3(): NodeProxy
137
+ toVec3(): NodeProxy
138
+ toBvec4(): NodeProxy
139
+ toIvec4(): NodeProxy
140
+ toUvec4(): NodeProxy
141
+ toVec4(): NodeProxy
142
+ toColor(): NodeProxy
143
+ toMat2(): NodeProxy
144
+ toMat3(): NodeProxy
145
+ toMat4(): NodeProxy
88
146
 
89
- // Math function methods
147
+ // Function methods
90
148
  abs(): NodeProxy
91
149
  sin(): NodeProxy
92
150
  cos(): NodeProxy
@@ -131,32 +189,8 @@ export interface NodeProxy extends Record<Swizzles, NodeProxy> {
131
189
  dFdx(): NodeProxy
132
190
  dFdy(): NodeProxy
133
191
  fwidth(): NodeProxy
134
-
135
- // System properties
136
- toBool(): NodeProxy
137
- toUint(): NodeProxy
138
- toInt(): NodeProxy
139
- toFloat(): NodeProxy
140
- toBvec2(): NodeProxy
141
- toIvec2(): NodeProxy
142
- toUvec2(): NodeProxy
143
- toVec2(): NodeProxy
144
- toBvec3(): NodeProxy
145
- toIvec3(): NodeProxy
146
- toUvec3(): NodeProxy
147
- toVec3(): NodeProxy
148
- toBvec4(): NodeProxy
149
- toIvec4(): NodeProxy
150
- toUvec4(): NodeProxy
151
- toVec4(): NodeProxy
152
- toColor(): NodeProxy
153
- toMat2(): NodeProxy
154
- toMat3(): NodeProxy
155
- toMat4(): NodeProxy
156
- toString(c?: NodeConfig): string
157
- type: NodeTypes
158
- props: NodeProps
159
- isProxy: true
160
192
  }
161
193
 
194
+ export type NodeProxy = BaseNodeProxy & DynamicProperties
195
+
162
196
  export type X = NodeProxy | number | string | boolean | undefined
package/src/node/utils.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { is } from '../utils/helpers'
2
2
  import { code } from './code'
3
- import { infer } from './infer'
4
3
  import {
5
4
  CONSTANTS,
6
5
  CONVERSIONS,
@@ -10,17 +9,7 @@ import {
10
9
  TYPE_MAPPING,
11
10
  WGSL_TO_GLSL_BUILTIN,
12
11
  } from './const'
13
- import type {
14
- Constants,
15
- Conversions,
16
- Functions,
17
- NodeConfig,
18
- NodeProps,
19
- NodeProxy,
20
- Operators,
21
- Swizzles,
22
- X,
23
- } from './types'
12
+ import type { Constants, Conversions, Functions, NodeContext, NodeProxy, Operators, Swizzles, X } from './types'
24
13
 
25
14
  export const isSwizzle = (key: unknown): key is Swizzles => {
26
15
  return is.str(key) && /^[xyzwrgbastpq]{1,4}$/.test(key)
@@ -44,6 +33,12 @@ export const isNodeProxy = (x: unknown): x is NodeProxy => {
44
33
  return x.isProxy
45
34
  }
46
35
 
36
+ export const isConstantsType = (type?: Constants | 'auto'): type is Constants => {
37
+ if (!type) return false
38
+ if (type === 'auto') return false
39
+ return true
40
+ }
41
+
47
42
  export const hex2rgb = (hex: number) => {
48
43
  const r = ((hex >> 16) & 0xff) / 255
49
44
  const g = ((hex >> 8) & 0xff) / 255
@@ -55,14 +50,14 @@ let count = 0
55
50
 
56
51
  export const getId = () => `i${count++}`
57
52
 
58
- export const joins = (children: X[], c: NodeConfig) => {
53
+ export const joins = (children: X[], c: NodeContext) => {
59
54
  return children
60
55
  .filter((x) => !is.und(x) && !is.nul(x))
61
56
  .map((x) => code(x, c))
62
57
  .join(', ')
63
58
  }
64
59
 
65
- export const formatConversions = (x: X, c?: NodeConfig) => {
60
+ export const formatConversions = (x: X, c?: NodeContext) => {
66
61
  if (!is.str(x)) return ''
67
62
  if (c?.isWebGL) return x
68
63
  return TYPE_MAPPING[x as keyof typeof TYPE_MAPPING]
@@ -80,81 +75,3 @@ export const conversionToConstant = (conversionKey: string): Constants => {
80
75
  const index = CONVERSIONS.indexOf(conversionKey as Conversions)
81
76
  return index !== -1 ? CONSTANTS[index] : 'float'
82
77
  }
83
-
84
- const generateHead = (c: NodeConfig) => {
85
- return Array.from(c.headers!)
86
- .map(([, v]) => v)
87
- .join('\n')
88
- }
89
-
90
- export const generateDefine = (props: NodeProps, c: NodeConfig) => {
91
- const { id, children = [], layout } = props
92
- const [x, y, ...args] = children
93
- const returnType = layout?.type && layout?.type !== 'auto' ? layout?.type : y ? infer(y, c) : 'void'
94
- const argParams: [name: string, type: string][] = []
95
- const params: string[] = []
96
- if (layout?.inputs)
97
- for (const input of layout.inputs) {
98
- argParams.push([input.name, input.type])
99
- }
100
- else
101
- for (let i = 0; i < args.length; i++) {
102
- argParams.push([`p${i}`, infer(args[i], c)])
103
- }
104
- let ret = ''
105
- if (c?.isWebGL) {
106
- for (const [id, type] of argParams) params.push(`${type} ${id}`)
107
- ret += `${returnType} ${id}(${params}) {\n`
108
- } else {
109
- for (const [id, type] of argParams) params.push(`${id}: ${formatConversions(type, c)}`)
110
- ret += `fn ${id}(${params}) -> ${formatConversions(returnType, c)} {\n`
111
- }
112
- const scopeCode = code(x, c)
113
- if (scopeCode) ret += scopeCode + '\n'
114
- if (y) ret += `return ${code(y, c)};`
115
- ret += '\n}'
116
- return ret
117
- }
118
-
119
- const GLSL_FRAGMENT_HEAD = `
120
- #version 300 es
121
- precision mediump float;
122
- out vec4 fragColor;
123
- `.trim()
124
-
125
- const WGSL_FRAGMENT_HEAD = `
126
- @fragment
127
- fn main(@builtin(position) position: vec4f) -> @location(0) vec4f {
128
- `.trim()
129
-
130
- const generateFragmentMain = (body: string, head: string, isWebGL = true) => {
131
- let ret = ''
132
- if (isWebGL) ret += GLSL_FRAGMENT_HEAD
133
- if (head) ret += '\n' + head + '\n'
134
- if (isWebGL) ret += `void main() {\n fragColor = ${body};`
135
- else {
136
- ret += WGSL_FRAGMENT_HEAD + '\n'
137
- ret += ` return ${body};`
138
- }
139
- ret += '\n}'
140
- return ret
141
- }
142
-
143
- const generateVertexMain = (_body: string, _head: string, isWebGL = true) => {
144
- if (isWebGL) return ``
145
- return ``
146
- }
147
-
148
- export const fragment = (x: X, c: NodeConfig = {}) => {
149
- const body = code(x, c)
150
- const head = generateHead(c)
151
- const main = generateFragmentMain(body, head, c.isWebGL)
152
- console.log(`// ↓↓↓ generated ↓↓↓\n\n${main}\n\n`)
153
- return main
154
- }
155
-
156
- export const vertex = (x: X, c: NodeConfig) => {
157
- const body = code(x, c)
158
- const head = generateHead(c)
159
- return generateVertexMain(body, head, c.isWebGL)
160
- }
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,27 @@ 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
+ }
30
+
31
+ export interface AttribData {
32
+ array: Float32Array
33
+ buffer: GPUBuffer
34
+ location: number
35
+ stride: number
36
+ }
37
+
26
38
  export interface WebGLState {
27
39
  context: WebGLRenderingContext
28
40
  program: WebGLProgram
@@ -30,14 +42,16 @@ export interface WebGLState {
30
42
 
31
43
  export interface WebGPUState {
32
44
  device: GPUDevice
33
- context: GPUContext
34
- pipeline: GPUPipeline
35
- groups: any[]
36
- resources: any[]
37
- loadingImg: number
38
- needsUpdate: boolean
45
+ uniforms: Nested<UniformData>
46
+ textures: Nested<TextureData>
47
+ attribs: Nested<AttribData>
39
48
  }
40
49
 
50
+ export type Uniform = number | number[]
51
+ export type Attribute = number[]
52
+ export type Attributes = Record<string, Attribute>
53
+ export type Uniforms = Record<string, Uniform>
54
+
41
55
  export type GL = EventState<{
42
56
  /**
43
57
  * initial value
@@ -84,6 +98,7 @@ export type GL = EventState<{
84
98
  */
85
99
  _uniform?(key: string, value: Uniform, isMatrix?: boolean): GL
86
100
  uniform(key: string, value: Uniform, isMatrix?: boolean): GL
101
+ uniform(node: NodeProxy): GL
87
102
  uniform(target: { [key: string]: Uniform }): GL
88
103
  _texture?(key: string, value: string): GL
89
104
  texture(key: string, value: string): GL