glre 0.30.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/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
@@ -1,44 +1,58 @@
1
- import { fragment, isNodeProxy, vertex } from '../node'
2
- import type { NodeProxy } from '../node'
3
- import type { GPUContext, GPUDevice, GPUPipeline } from '../types'
1
+ import { fragment, vertex } from '../node'
2
+ import type { X } from '../node'
3
+ import type { AttribData, TextureData, UniformData, WebGPUState } from '../types'
4
+ import { is } from './helpers'
4
5
 
5
- const defaultVertexWGSL = `
6
- @vertex
7
- fn main(@builtin(vertex_index) vertex_index: u32) -> @builtin(position) vec4f {
8
- let x = f32(vertex_index % 2u) * 4.0 - 1.0;
9
- let y = f32(vertex_index / 2u) * 4.0 - 1.0;
10
- return vec4f(x, y, 0.0, 1.0);
11
- }
12
- `
13
-
14
- const defaultFragmentWGSL = `
15
- @group(0) @binding(0) var<uniform> iResolution: vec2f;
16
-
17
- @fragment
18
- fn main(@builtin(position) position: vec4f) -> @location(0) vec4f {
19
- return vec4f(position.xy / iResolution, 0.0, 1.0);
20
- }
21
- `
22
-
23
- export const createDevice = async (c: GPUContext) => {
24
- const gpu = (navigator as any).gpu
6
+ /**
7
+ * initialize
8
+ */
9
+ export const createDevice = async (c: GPUCanvasContext) => {
10
+ const gpu = navigator.gpu
25
11
  const format = gpu.getPreferredCanvasFormat()
26
12
  const adapter = await gpu.requestAdapter()
27
- const device = await adapter.requestDevice()
13
+ const device = await adapter!.requestDevice()
28
14
  c.configure({ device, format, alphaMode: 'opaque' })
29
15
  return { device, format }
30
16
  }
31
17
 
18
+ export const createBindings = () => {
19
+ let uniform = 0
20
+ let texture = 0
21
+ let attrib = 0
22
+ return {
23
+ uniform: () => {
24
+ const group = Math.floor(uniform / 12)
25
+ const binding = uniform % 12
26
+ uniform++
27
+ return { group, binding }
28
+ },
29
+ texture: () => {
30
+ const baseGroup = Math.floor(uniform / 12) + 1
31
+ const group = baseGroup + Math.floor(texture / 6)
32
+ const binding = (texture % 6) * 2
33
+ texture++
34
+ return { group, binding }
35
+ },
36
+ attrib: () => {
37
+ const location = attrib
38
+ attrib++
39
+ return { location }
40
+ },
41
+ }
42
+ }
43
+
32
44
  export const createPipeline = (
33
45
  device: GPUDevice,
34
- format: string,
35
- bufferLayouts: any[],
36
- bindGroupLayouts: any[],
37
- vs: string | NodeProxy = defaultVertexWGSL,
38
- fs: string | NodeProxy = defaultFragmentWGSL
46
+ format: GPUTextureFormat,
47
+ bufferLayouts: GPUVertexBufferLayout[],
48
+ bindGroupLayouts: GPUBindGroupLayout[],
49
+ webgpu: WebGPUState,
50
+ vs: string | X,
51
+ fs: string | X
39
52
  ) => {
40
- if (isNodeProxy(vs)) vs = vertex(vs, { isWebGL: false })
41
- if (isNodeProxy(fs)) fs = fragment(fs, { isWebGL: false })
53
+ const config = { isWebGL: false, webgpu }
54
+ if (!is.str(fs)) fs = fragment(fs, config)
55
+ if (!is.str(vs)) vs = vertex(vs, config)
42
56
  const layout = device.createPipelineLayout({ bindGroupLayouts })
43
57
  return device.createRenderPipeline({
44
58
  vertex: {
@@ -53,83 +67,121 @@ export const createPipeline = (
53
67
  },
54
68
  layout,
55
69
  primitive: { topology: 'triangle-list' },
56
- }) as GPUPipeline
70
+ depthStencil: {
71
+ depthWriteEnabled: true,
72
+ depthCompare: 'less',
73
+ format: 'depth24plus',
74
+ },
75
+ })
57
76
  }
58
77
 
59
- export const createBindGroup = (device: GPUDevice, resources: any[]) => {
60
- const entries0 = [] as any[]
61
- const entries1 = [] as any[]
62
- resources.forEach((resource, binding) => {
63
- if (!resource) return
64
- const isUniform = 'buffer' in resource // @ts-ignore
65
- const isTexture = resource instanceof GPUTextureView // @ts-ignore
66
- const isSampler = resource instanceof GPUSampler // @ts-ignore
67
- if (isUniform) entries0.push({ binding, visibility: 3, buffer: { type: 'uniform' } })
68
- else if (isTexture) entries0.push({ binding, visibility: 2, texture: {} })
69
- else if (isSampler) entries0.push({ binding, visibility: 2, sampler: {} })
70
- else return
71
- entries1.push({ binding, resource })
72
- })
73
- const layout = device.createBindGroupLayout({ entries: entries0 })
74
- const bindGroup = device.createBindGroup({ layout, entries: entries1 })
75
- return { layout, bindGroup }
78
+ /**
79
+ * buffers
80
+ */
81
+ export const createUniformBuffer = (device: GPUDevice, value: number[]) => {
82
+ const array = new Float32Array(value)
83
+ const size = Math.ceil(array.byteLength / 256) * 256
84
+ const buffer = device.createBuffer({ size, usage: 72 }) // 72 is GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
85
+ return { array, buffer }
76
86
  }
77
87
 
78
- export const createDescriptor = (c: GPUContext) => {
88
+ export const createAttribBuffer = (device: GPUDevice, value: number[]) => {
89
+ const array = new Float32Array(value)
90
+ const buffer = device.createBuffer({ size: array.byteLength, usage: 40 }) // 40 is GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
91
+ return { array, buffer }
92
+ }
93
+
94
+ /**
95
+ * uniforms
96
+ */
97
+ export const createBindGroup = (
98
+ device: GPUDevice,
99
+ uniforms: Map<string, UniformData>,
100
+ textures: Map<string, TextureData>
101
+ ) => {
102
+ const groups = new Map<number, any>()
103
+ const getGroup = (i = 0) => {
104
+ if (!groups.has(i)) groups.set(i, { entries0: [], entries1: [] })
105
+ return groups.get(i)
106
+ }
107
+ for (const { binding, buffer, group: i } of uniforms.values()) {
108
+ const { entries0, entries1 } = getGroup(i)
109
+ entries0.push({ binding, visibility: 3, buffer: { type: 'uniform' } })
110
+ entries1.push({ binding, resource: { buffer } })
111
+ }
112
+ for (const { binding, group: i, sampler, texture } of textures.values()) {
113
+ const { entries0, entries1 } = getGroup(i)
114
+ entries0.push({ binding, visibility: 2, sampler: {} })
115
+ entries0.push({ binding: binding + 1, visibility: 2, texture: {} })
116
+ entries1.push({ binding, resource: sampler })
117
+ entries1.push({ binding: binding + 1, resource: texture.createView() })
118
+ }
119
+ const ret = { bindGroups: [] as GPUBindGroup[], bindGroupLayouts: [] as GPUBindGroupLayout[] }
120
+ for (const [i, { entries0, entries1 }] of groups) {
121
+ ret.bindGroupLayouts[i] = device.createBindGroupLayout({ entries: entries0 })
122
+ ret.bindGroups[i] = device.createBindGroup({ layout: ret.bindGroupLayouts[i], entries: entries1 })
123
+ }
124
+ return ret
125
+ }
126
+
127
+ export const createDescriptor = (c: GPUCanvasContext, depthTexture: GPUTexture) => {
79
128
  return {
80
129
  colorAttachments: [
81
130
  {
82
131
  view: c.getCurrentTexture().createView(),
83
132
  clearValue: { r: 0, g: 0, b: 0, a: 1 },
84
- loadOp: 'clear',
85
- storeOp: 'store',
133
+ loadOp: 'clear' as GPULoadOp,
134
+ storeOp: 'store' as GPUStoreOp,
86
135
  },
87
136
  ],
88
- }
89
- }
90
-
91
- export const alignTo256 = (size: number) => Math.ceil(size / 256) * 256
92
-
93
- export const createVertexBuffer = (device: GPUDevice, value: number[]) => {
94
- const array = new Float32Array(value)
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 }
137
+ depthStencilAttachment: {
138
+ view: depthTexture.createView(),
139
+ depthClearValue: 1.0,
140
+ depthLoadOp: 'clear' as GPULoadOp,
141
+ depthStoreOp: 'store' as GPUStoreOp,
142
+ },
143
+ } as GPURenderPassDescriptor
104
144
  }
105
145
 
106
146
  export const createTextureSampler = (device: GPUDevice, width = 1280, height = 800) => {
107
- const texture = device.createTexture({ size: [width, height], format: 'rgba8unorm', usage: 22 })
147
+ const texture = device.createTexture({ size: [width, height], format: 'rgba8unorm', usage: 22 }) // 22 is GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT
108
148
  const sampler = device.createSampler({ magFilter: 'linear', minFilter: 'linear' })
109
149
  return { texture, sampler }
110
150
  }
111
151
 
112
- const getVertexStride = (dataLength: number, vertexCount: number) => {
113
- return dataLength / vertexCount
152
+ export const createDepthTexture = (device: GPUDevice, width: number, height: number) => {
153
+ return device.createTexture({
154
+ size: [width, height],
155
+ format: 'depth24plus',
156
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
157
+ })
114
158
  }
115
159
 
116
- const getVertexFormat = (stride: number) => {
160
+ /**
161
+ * attribs
162
+ */
163
+ const getVertexFormat = (stride: number): GPUVertexFormat => {
117
164
  if (stride === 2) return 'float32x2'
118
165
  if (stride === 3) return 'float32x3'
119
166
  if (stride === 4) return 'float32x4'
120
167
  return 'float32'
121
168
  }
122
169
 
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
- ],
170
+ export const createVertexBuffers = (attribs: Map<string, AttribData>) => {
171
+ const vertexBuffers: GPUBuffer[] = []
172
+ const bufferLayouts: GPUVertexBufferLayout[] = []
173
+ for (const [, { buffer, location, stride }] of attribs) {
174
+ vertexBuffers[location] = buffer
175
+ bufferLayouts[location] = {
176
+ arrayStride: stride * 4,
177
+ attributes: [
178
+ {
179
+ shaderLocation: location,
180
+ offset: 0,
181
+ format: getVertexFormat(stride),
182
+ },
183
+ ],
184
+ }
134
185
  }
186
+ return { vertexBuffers, bufferLayouts }
135
187
  }