@bigmistqke/view.gl 0.4.0 → 0.5.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/README.md CHANGED
@@ -319,26 +319,38 @@ const interleavedAttributes = interleavedAttributeView(gl, program, {
319
319
  },
320
320
  })
321
321
 
322
- interleavedAttributes.vertexData.set(interleavedVertexData).bind()
322
+ interleavedAttributes.vertexData.buffer.set(interleavedVertexData)
323
323
  ```
324
324
 
325
- Where vertex array objects are available this binds one, and it stays selected
326
- for every later draw — which would then write its own attributes into it. The
327
- disposer returned by `bind()` selects the previous array again:
325
+ Where vertex array objects are available `bind()` binds one, and it stays
326
+ selected for every later draw — which would then write its own attributes into
327
+ it. The disposer returned by `bind()` selects the previous array again:
328
328
 
329
329
  ```typescript
330
- const unbind = interleavedAttributes.vertexData.bind()
330
+ const unbind = interleavedAttributes.vertexData.buffer.bind()
331
331
  gl.drawElements(gl.TRIANGLES, count, gl.UNSIGNED_SHORT, 0)
332
332
  unbind()
333
333
  ```
334
334
 
335
+ Whether the buffer steps once per vertex or once per instance is chosen per
336
+ draw, not in the schema: `buffer` steps per vertex, `buffer.perInstance` per
337
+ instance. `constant` sets the same layout as constant attribute values, for a
338
+ draw that needs one set of values without a buffer.
339
+
340
+ A large buffer can be sized first and filled in parts, so it never has to exist
341
+ whole in JavaScript. Both count in floats:
342
+
343
+ ```typescript
344
+ const { buffer } = interleavedAttributes.vertexData
345
+ buffer.allocate(totalFloats) // sizes the buffer, contents undefined
346
+ buffer.write(chunk, offsetFloats) // overwrites a range with bufferSubData
347
+ ```
348
+
335
349
  ##### 📋 InterleavedAttributeSchema
336
350
 
337
351
  A mapping of interleaved buffer names to their layout configuration. Each layout defines multiple attributes packed into a single buffer.
338
352
 
339
353
  - `layout`: Array of attribute definitions with `key` and `kind` (see [Attribute Types](#-attribute-types))
340
- - `instanced`: Boolean - applies to all attributes in layout
341
- - `buffer`: Custom WebGLBuffer (optional) - by default it gets created automatically during compilation
342
354
 
343
355
  <details>
344
356
  <summary>TypeScript Types</summary>
@@ -349,8 +361,6 @@ interface InterleavedAttributeDefinition {
349
361
  key: string | symbol
350
362
  kind: AttributeKind
351
363
  }>
352
- instanced?: boolean // Applies vertexAttribDivisor to all attributes
353
- buffer?: WebGLBuffer // Custom buffer for interleaved data
354
364
  }
355
365
 
356
366
  type InterleavedAttributeSchema = Record<string | symbol, InterleavedAttributeDefinition>
@@ -376,6 +376,14 @@ function interleavedAttributeView(gl, program, schema, { signal } = {}) {
376
376
  set(value, usage = "STATIC_DRAW") {
377
377
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
378
378
  gl.bufferData(gl.ARRAY_BUFFER, value, gl[usage]);
379
+ },
380
+ allocate(length, usage = "STATIC_DRAW") {
381
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
382
+ gl.bufferData(gl.ARRAY_BUFFER, length * Float32Array.BYTES_PER_ELEMENT, gl[usage]);
383
+ },
384
+ write(data, offset) {
385
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
386
+ gl.bufferSubData(gl.ARRAY_BUFFER, offset * Float32Array.BYTES_PER_ELEMENT, data);
379
387
  }
380
388
  }),
381
389
  // Lazy: a layout key can be perfectly good in a buffer and impossible as
@@ -433,4 +441,4 @@ export {
433
441
  interleavedAttributeView,
434
442
  bufferView
435
443
  };
436
- //# sourceMappingURL=chunk-H56LJYS5.mjs.map
444
+ //# sourceMappingURL=chunk-H4K75BIR.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { getInstancedArrays, getVertexArrayObject } from './gl'\nimport type {\n AttributeFormat,\n AttributeKind,\n AttributeMethods,\n AttributeSchema,\n AttributeView,\n BufferSchema,\n BufferView,\n GL,\n UniformView as InferUniformView,\n GLUsage,\n InterleavedAttributeLayout,\n InterleavedAttributeMethods,\n InterleavedAttributeSchema,\n InterleavedAttributeView,\n UniformSchema,\n VertexArrayMethods,\n VertexArrayParticipant,\n View,\n ViewOptions,\n ViewSchema,\n} from './types'\nimport {\n isSamplerKind,\n kindToUniformFnName,\n isMatKind,\n assertedNotNullish,\n kindToSize,\n forEachObject,\n once,\n} from './utils'\nimport { createUpsertMap, mapObject } from './utils'\nexport * from './types'\n// Documented under Utils but reachable from nowhere until now: utils is not a\n// build entry, and named rather than star so the internal helpers stay internal.\nexport { createFramebuffer, createTexture } from './utils'\n\n/**********************************************************************************/\n/* */\n/* To ID */\n/* */\n/**********************************************************************************/\n\nlet index = 0\nconst PREFIX = 'VIEW_GL_ALIAS'\n// Firefox has currently a bug where it can not handle symbol as WeakRef / key for WeakMap\n// see https://bugzilla.mozilla.org/show_bug.cgi?id=1710433\nconst HAS_WEAK_SYMBOL = (() => {\n try {\n const symbol = Symbol()\n new WeakMap().set(symbol, '')\n return true\n } catch {\n return false\n }\n})()\n// NOTE: fallback to Map will currently cause a minor memory leak.\nconst SYMBOL_MAP = createUpsertMap(HAS_WEAK_SYMBOL ? WeakMap<symbol, string> : Map<symbol, string>)\n\nexport function toID(key: string | number | symbol) {\n if (typeof key === 'string') {\n return key\n }\n if (typeof key === 'symbol') {\n return SYMBOL_MAP.getOrInsert(key, () => `${PREFIX}_${index++}`)\n }\n return key.toString()\n}\n\n/**********************************************************************************/\n/* */\n/* View */\n/* */\n/**********************************************************************************/\n\nexport function view<TSchema extends ViewSchema>(\n gl: GL,\n program: WebGLProgram,\n schema: TSchema,\n { signal }: ViewOptions = {},\n): View<TSchema> {\n // The sub-views are built without the signal and the view wires disposal\n // once, so that `dispose()` and aborting do the same thing rather than each\n // doing half of it.\n const attributes = !schema.attributes ? undefined : attributeView(gl, program, schema.attributes)\n const interleavedAttributes = !schema.interleavedAttributes\n ? undefined\n : interleavedAttributeView(gl, program, schema.interleavedAttributes)\n // Owned by the view, on the view's signal. This is the line the split was\n // really about: it used to read `bufferView(gl, schema.buffers)` with the\n // options dropped, so a view's buffers were the only resources that still\n // needed disposing by hand. That was a missing argument rather than a wrong\n // model — a buffer whose lifetime IS the view's belongs with it.\n const buffers = !schema.buffers ? undefined : bufferView(gl, schema.buffers)\n\n // Vertex arrays are made on demand rather than declared, so they are the one\n // thing the view cannot dispose from the schema alone. Held until disposed —\n // by the view or by the caller — and dropped either way, so a view that hands\n // out an array per frame does not accumulate them.\n const vertexArrays = new Set<VertexArrayMethods>()\n\n const dispose = once(() => {\n if (attributes) forEachObject(attributes, value => value.dispose())\n if (interleavedAttributes) forEachObject(interleavedAttributes, value => value.dispose())\n if (buffers) forEachObject(buffers, value => value.dispose())\n vertexArrays.forEach(vertexArray => vertexArray.dispose())\n vertexArrays.clear()\n })\n\n signal?.addEventListener('abort', dispose)\n\n return {\n uniforms: !schema.uniforms ? undefined : uniformView(gl, program, schema.uniforms),\n attributes,\n interleavedAttributes,\n buffers,\n vao(participants: VertexArrayParticipant[]) {\n const vertexArray = vaoView(gl, participants)\n vertexArrays.add(vertexArray)\n return {\n ...vertexArray,\n dispose: once(() => {\n vertexArrays.delete(vertexArray)\n vertexArray.dispose()\n }),\n }\n },\n dispose,\n } as View<TSchema>\n}\n\n/**********************************************************************************/\n/* */\n/* Vertex Array */\n/* */\n/**********************************************************************************/\n\n/**\n * Bind the default vertex array, returning a disposer that puts the previous\n * one back. The pointer calls name no destination, so anything applied without\n * a vertex array of its own has to say which one it means — and a vertex array\n * keeps what it is given, so writing into a caller's array by accident would\n * outlive the call that did it.\n */\nfunction bindDefaultVertexArray(gl: GL): () => void {\n const feature = getVertexArrayObject(gl)\n if (!feature) {\n return () => {}\n }\n const previous = gl.getParameter(VERTEX_ARRAY_BINDING) as WebGLVertexArrayObject | null\n feature.bindVertexArray(null)\n return () => feature.bindVertexArray(previous)\n}\n\n/**\n * A vertex array over the participants one draw needs.\n *\n * Where the context has vertex arrays, each participant writes itself in once,\n * here, and `bind()` is a single `bindVertexArray`. Where it does not — WebGL1\n * without `OES_vertex_array_object` — there is nowhere to keep the state, so\n * `bind()` re-applies every participant and the disposer puts back what they\n * displaced. Same contract, and the emulation is why the name still fits.\n */\nexport function vaoView(\n gl: GL,\n participants: VertexArrayParticipant[],\n { signal }: ViewOptions = {},\n): VertexArrayMethods {\n const feature = getVertexArrayObject(gl)\n\n const methods: VertexArrayMethods = !feature\n ? {\n bind() {\n const restores = participants.map(participant => participant.applyToVertexArray())\n participants.forEach(participant => participant.applyToContext?.())\n return once(() => restores.forEach(restore => restore()))\n },\n unbind() {},\n dispose() {},\n }\n : (() => {\n const vertexArray = assertedNotNullish(feature.createVertexArray())\n const previous = gl.getParameter(VERTEX_ARRAY_BINDING) as WebGLVertexArrayObject | null\n feature.bindVertexArray(vertexArray)\n // Discarding the restorers is the point: the state lives in this array\n // now, and the array is thrown away whole.\n for (const participant of participants) {\n participant.applyToVertexArray()\n }\n feature.bindVertexArray(previous)\n\n return {\n bind() {\n const previousVertexArray = gl.getParameter(\n VERTEX_ARRAY_BINDING,\n ) as WebGLVertexArrayObject | null\n feature.bindVertexArray(vertexArray)\n // Context state the array cannot hold — see applyToContext.\n participants.forEach(participant => participant.applyToContext?.())\n return once(() => feature.bindVertexArray(previousVertexArray))\n },\n unbind() {\n feature.bindVertexArray(null)\n },\n dispose: once(() => feature.deleteVertexArray(vertexArray)),\n }\n })()\n\n signal?.addEventListener('abort', () => methods.dispose())\n\n return methods\n}\n\n/**********************************************************************************/\n/* */\n/* Uniform View */\n/* */\n/**********************************************************************************/\n\nexport function uniformView<T extends UniformSchema>(\n gl: GL,\n program: WebGLProgram,\n schema: T,\n): InferUniformView<T> {\n // @ts-expect-error - conditional return type based on size is hard to infer\n return mapObject(schema, ({ kind, size }, key) => {\n const name = toID(key)\n\n if (isSamplerKind(kind)) {\n const location = gl.getUniformLocation(program, name)\n return {\n set(arg: number) {\n gl.uniform1i(location, arg)\n },\n }\n }\n\n // Array uniform - support both bulk set and indexed access\n if (size) {\n const bulkFnName = `uniform${kindToUniformFnName(kind)}v`\n // @ts-ignore FIX WEBGL/WEBGL2 TYPES\n const bulkFn = gl[bulkFnName].bind(gl)\n const bulkLocation = gl.getUniformLocation(program, name)\n\n const elementFnName = `uniform${kindToUniformFnName(kind)}`\n // @ts-ignore FIX WEBGL/WEBGL2 TYPES\n const elementFn = gl[elementFnName].bind(gl)\n\n // Build array of element setters\n const elements: Array<{ set(...args: any[]): void }> = []\n for (let i = 0; i < size; i++) {\n const location = gl.getUniformLocation(program, `${name}[${i}]`)\n elements[i] = {\n set(...args: any[]) {\n elementFn(location, ...args)\n },\n }\n }\n\n // Return array-like object with bulk set\n return Object.assign(elements, {\n set(arg: Float32Array) {\n bulkFn(bulkLocation, arg)\n },\n })\n }\n\n // Non-array uniform\n const location = gl.getUniformLocation(program, name)\n const fnName = `uniform${kindToUniformFnName(kind)}`\n\n // @ts-ignore FIX WEBGL/WEBGL2 TYPES\n const fn = gl[fnName].bind(gl)\n\n if (isMatKind(kind)) {\n return {\n set(...args: any[]) {\n fn(location, false, args[0])\n },\n }\n }\n\n return {\n set(...args: any[]) {\n fn(location, ...args)\n },\n }\n })\n}\n\n/**********************************************************************************/\n/* */\n/* Attribute View */\n/* */\n/**********************************************************************************/\n\ntype GLType =\n | 'FLOAT'\n | 'INT'\n | 'UNSIGNED_INT'\n | 'SHORT'\n | 'UNSIGNED_SHORT'\n | 'BYTE'\n | 'UNSIGNED_BYTE'\n\nconst FORMAT_TO_GL_TYPE: Record<AttributeFormat, GLType> = {\n float32: 'FLOAT',\n int32: 'INT',\n uint32: 'UNSIGNED_INT',\n int16: 'SHORT',\n uint16: 'UNSIGNED_SHORT',\n int8: 'BYTE',\n uint8: 'UNSIGNED_BYTE',\n}\n\nconst FORMAT_BYTE_SIZE: Record<AttributeFormat, number> = {\n float32: 4,\n int32: 4,\n uint32: 4,\n int16: 2,\n uint16: 2,\n int8: 1,\n uint8: 1,\n}\n\nfunction defaultFormat(kind: AttributeKind): AttributeFormat {\n if (kind.startsWith('u')) return 'uint32'\n if (kind.startsWith('i')) return 'int32'\n return 'float32'\n}\n\n// Shared attribute helper functions\n// between attributeView and interleavedAttributeView\nfunction handleAttribute(\n gl: GL,\n location: number,\n size: number,\n stride: number,\n offset: number,\n glType: GLType,\n isIntegerKind: boolean,\n normalized: boolean,\n instanced?: boolean,\n) {\n gl.enableVertexAttribArray(location)\n if (isIntegerKind) {\n ;(gl as WebGL2RenderingContext).vertexAttribIPointer(location, size, gl[glType], stride, offset)\n } else {\n gl.vertexAttribPointer(location, size, gl[glType], normalized, stride, offset)\n }\n\n // Always stated, never inherited: the divisor belongs to the location rather\n // than to the program, so a location left at 1 by an earlier instanced\n // attribute would feed one value to every vertex here.\n // Get instanced-arrays-feature: extension if webgl, gl if webgl2\n const instancedArrays = getInstancedArrays(gl)\n if (instanced) {\n assertedNotNullish(instancedArrays).vertexAttribDivisor(location, 1)\n } else if (instancedArrays) {\n instancedArrays.vertexAttribDivisor(location, 0)\n }\n}\n\n// Same enum in webgl2 and in the webgl1 extensions, which expose no constants\nconst VERTEX_ATTRIB_ARRAY_DIVISOR = 0x88fe\nconst VERTEX_ARRAY_BINDING = 0x85b5\n\n// Reads the divisor currently attached to a location, 0 where instancing is\n// unavailable and nothing can have set one\nfunction readDivisor(gl: GL, location: number): number {\n return getInstancedArrays(gl)\n ? (gl.getVertexAttrib(location, VERTEX_ATTRIB_ARRAY_DIVISOR) as number)\n : 0\n}\n\nexport function attributeView<T extends AttributeSchema>(\n gl: GL,\n program: WebGLProgram,\n schema: T,\n { signal }: ViewOptions = {},\n): AttributeView<T> {\n const attributes = mapObject(\n schema,\n (\n { kind, format, normalized = false, instanced, buffer: providedBuffer },\n key,\n ): AttributeMethods => {\n const name = toID(key)\n\n // Whoever made the buffer deletes it. A schema can name a buffer that\n // belongs to another view — the quad `compile.toQuad` shares across every\n // program on a context, an attribute two programs step over — and\n // deleting one of those would take it out from under its owner.\n const buffer = providedBuffer ?? assertedNotNullish(gl.createBuffer())\n\n const location = gl.getAttribLocation(program, name)\n if (location < 0) {\n throw new Error(`Attribute '${name}' not found`)\n }\n\n const size = kindToSize(kind)\n const resolvedFormat = format ?? defaultFormat(kind)\n const glType = FORMAT_TO_GL_TYPE[resolvedFormat]\n const isIntKind = kind.startsWith('i') || kind.startsWith('u')\n\n function applyToVertexArray() {\n // Snapshot before the change, restore in the disposer\n const previousDivisor = readDivisor(gl, location)\n // vertexAttribPointer captures whatever is bound to ARRAY_BUFFER when\n // it runs, so this binding is the setup for the pointer, not a lasting\n // part of the vertex array's state.\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n handleAttribute(gl, location, size, 0, 0, glType, isIntKind, normalized, instanced)\n return once(() => {\n getInstancedArrays(gl)?.vertexAttribDivisor(location, previousDivisor)\n })\n }\n\n return {\n buffer,\n applyToVertexArray,\n bind() {\n const restoreVertexArray = bindDefaultVertexArray(gl)\n const restore = applyToVertexArray()\n return once(() => {\n restore()\n restoreVertexArray()\n })\n },\n dispose: once(() => {\n if (!providedBuffer) {\n gl.deleteBuffer(buffer)\n }\n }),\n set(data, usage = 'STATIC_DRAW') {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n gl.bufferData(gl.ARRAY_BUFFER, data, gl[usage])\n return this\n },\n }\n },\n )\n\n signal?.addEventListener('abort', function dispose() {\n forEachObject(attributes, value => value.dispose())\n })\n\n return attributes\n}\n\n/**********************************************************************************/\n/* */\n/* Interleaved Attribute View */\n/* */\n/**********************************************************************************/\n\n/**\n * The other place an attribute's value can come from: not a buffer, but the\n * context's current generic vertex attribute values, which an attribute reads\n * for every vertex when its array is disabled.\n *\n * A constant is a uniform in all but name — one value for the whole draw, set\n * by a function chosen from the kind — so it gets the setters a uniform gets,\n * off the same layout the buffer source uses.\n *\n * `vertexAttrib*` tops out at four floats and has no matrix form, so a layout\n * key that is fine in a buffer can be impossible as a constant. That is a hard\n * limit of the API rather than a choice, and it is worth saying so out loud at\n * the point someone reaches for it.\n */\nfunction constantSource(gl: GL, layout: InterleavedAttributeLayout[], locations: number[]) {\n const setters = layout.map((entry, index) => {\n const size = kindToSize(entry.kind)\n const name = toID(entry.key)\n if (isMatKind(entry.kind) || size > 4) {\n throw new Error(\n `'${name}' is a ${entry.kind}, which cannot be a constant attribute: vertexAttrib* takes at most 4 floats and has no matrix form. Use the buffer source for it.`,\n )\n }\n // The values are context state, not vertex-array state, so they are held\n // here and written again on every bind — see applyToContext.\n let values: number[] = []\n const fn = gl[`vertexAttrib${size as 1 | 2 | 3 | 4}f`].bind(gl)\n return {\n name,\n location: locations[index]!,\n write: () => {\n if (values.length) {\n ;(fn as (location: number, ...args: number[]) => void)(locations[index]!, ...values)\n }\n },\n methods: {\n set(...args: number[]) {\n values = args\n },\n },\n }\n })\n\n return Object.assign(Object.fromEntries(setters.map(setter => [setter.name, setter.methods])), {\n applyToVertexArray() {\n const restores = setters.map(({ location }) => {\n const wasEnabled = gl.getVertexAttrib(location, gl.VERTEX_ATTRIB_ARRAY_ENABLED) as boolean\n gl.disableVertexAttribArray(location)\n return () => (wasEnabled ? gl.enableVertexAttribArray(location) : undefined)\n })\n return once(() => restores.forEach(restore => restore()))\n },\n applyToContext() {\n setters.forEach(setter => setter.write())\n },\n bind() {\n const restoreVertexArray = bindDefaultVertexArray(gl)\n const restore = this.applyToVertexArray()\n this.applyToContext()\n return once(() => {\n restore()\n restoreVertexArray()\n })\n },\n })\n}\n\nexport function interleavedAttributeView<T extends InterleavedAttributeSchema>(\n gl: GL,\n program: WebGLProgram,\n schema: T,\n { signal }: ViewOptions = {},\n): InterleavedAttributeView<T> {\n // Initialize interleaved attributes\n const interleavedAttributes = mapObject(schema, ({ layout }) => {\n // Increment number to keep track of offset\n let index = 0\n\n // Calculate layout information\n const locations: number[] = []\n const handles = layout.map(layout => {\n const name = toID(layout.key)\n\n const location = gl.getAttribLocation(program, name)\n\n if (location < 0) {\n throw new Error(`Attribute '${name}' not found`)\n }\n\n locations.push(location)\n\n const size = kindToSize(layout.kind)\n const offset = index\n const resolvedFormat = layout.format ?? defaultFormat(layout.kind)\n const glType = FORMAT_TO_GL_TYPE[resolvedFormat]\n const isIntKind = layout.kind.startsWith('i') || layout.kind.startsWith('u')\n const normalized = layout.normalized ?? false\n index += size * FORMAT_BYTE_SIZE[resolvedFormat]\n\n return (divisor: 0 | 1) =>\n handleAttribute(\n gl,\n location,\n size,\n stride,\n offset,\n glType,\n isIntKind,\n normalized,\n divisor === 1,\n )\n })\n\n // Set stride to final index\n const stride = index\n\n // Create a buffer\n const buffer = assertedNotNullish(gl.createBuffer())\n\n // This layout used to create a vertex array of its own, here, which is why\n // the other participants in a draw had to be bound after it to be included\n // — the array they landed in was whichever one happened to be current.\n // Arrays are `vao()`'s job now; a layout is a layout and a buffer.\n function applyToVertexArray(divisor: 0 | 1) {\n const previousDivisors = locations.map(\n location => [location, readDivisor(gl, location)] as const,\n )\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n for (const handle of handles) {\n handle(divisor)\n }\n return once(() => {\n const instancedArrays = getInstancedArrays(gl)\n previousDivisors.forEach(([location, previous]) => {\n instancedArrays?.vertexAttribDivisor(location, previous)\n })\n })\n }\n\n let constant: ReturnType<typeof constantSource> | undefined\n\n /** One layout, one buffer, but a divisor per draw rather than per schema. */\n function bufferSource(divisor: 0 | 1) {\n const apply = () => applyToVertexArray(divisor)\n return {\n applyToVertexArray: apply,\n bind() {\n const restoreVertexArray = bindDefaultVertexArray(gl)\n const restore = apply()\n return once(() => {\n restore()\n restoreVertexArray()\n })\n },\n }\n }\n\n return {\n buffer: Object.assign(bufferSource(0), {\n /** The same buffer, stepped once per instance instead of once per vertex. */\n perInstance: bufferSource(1),\n set(value: Float32Array, usage: GLUsage = 'STATIC_DRAW') {\n // Uploading is storage, not binding: ARRAY_BUFFER is not vertex-array\n // state, so this touches no array, whichever one is bound.\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n gl.bufferData(gl.ARRAY_BUFFER, value, gl[usage])\n },\n }),\n // Lazy: a layout key can be perfectly good in a buffer and impossible as\n // a constant, and finding that out should wait until someone asks for one.\n get constant() {\n return (constant ??= constantSource(gl, layout, locations))\n },\n dispose: once(() => gl.deleteBuffer(buffer)),\n } satisfies InterleavedAttributeMethods\n })\n\n signal?.addEventListener('abort', function dispose() {\n forEachObject(interleavedAttributes, value => value.dispose())\n })\n\n return interleavedAttributes\n}\n\n/**********************************************************************************/\n/* */\n/* Buffer View */\n/* */\n/**********************************************************************************/\n\nexport function bufferView<T extends BufferSchema>(\n gl: GL,\n schema: T,\n { signal }: ViewOptions = {},\n): BufferView<T> {\n // Initialize buffers\n const buffers = mapObject(schema, ({ target = 'ARRAY_BUFFER', usage = 'STATIC_DRAW' }) => {\n const buffer = assertedNotNullish(gl.createBuffer())\n\n function applyToVertexArray() {\n // Snapshot before the change, restore in the disposer. Restoring the\n // previous buffer rather than null matters for ELEMENT_ARRAY_BUFFER,\n // whose binding is recorded in the bound vertex array: clearing it\n // would strip the index buffer from an array the caller may not own.\n const previousBuffer = gl.getParameter(gl[`${target}_BINDING`]) as WebGLBuffer | null\n gl.bindBuffer(gl[target], buffer)\n return once(() => {\n gl.bindBuffer(gl[target], previousBuffer)\n })\n }\n\n return {\n applyToVertexArray,\n bind() {\n // ELEMENT_ARRAY_BUFFER's binding belongs to the bound vertex array, so\n // like the attributes this has to say which array it means. ARRAY_BUFFER\n // is context state and unaffected either way.\n const restoreVertexArray = bindDefaultVertexArray(gl)\n const restore = applyToVertexArray()\n return once(() => {\n restore()\n restoreVertexArray()\n })\n },\n dispose: once(() => gl.deleteBuffer(buffer)),\n set(data: Float32Array) {\n gl.bindBuffer(gl[target], buffer)\n gl.bufferData(gl[target], data, gl[usage])\n },\n }\n })\n\n signal?.addEventListener('abort', function dispose() {\n forEachObject(buffers, value => value.dispose())\n })\n\n return buffers\n}\n"],"mappings":"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","names":["location","index","layout"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { getInstancedArrays, getVertexArrayObject } from './gl'\nimport type {\n AttributeFormat,\n AttributeKind,\n AttributeMethods,\n AttributeSchema,\n AttributeView,\n BufferSchema,\n BufferView,\n GL,\n UniformView as InferUniformView,\n GLUsage,\n InterleavedAttributeLayout,\n InterleavedAttributeMethods,\n InterleavedAttributeSchema,\n InterleavedAttributeView,\n UniformSchema,\n VertexArrayMethods,\n VertexArrayParticipant,\n View,\n ViewOptions,\n ViewSchema,\n} from './types'\nimport {\n isSamplerKind,\n kindToUniformFnName,\n isMatKind,\n assertedNotNullish,\n kindToSize,\n forEachObject,\n once,\n} from './utils'\nimport { createUpsertMap, mapObject } from './utils'\nexport * from './types'\n// Documented under Utils but reachable from nowhere until now: utils is not a\n// build entry, and named rather than star so the internal helpers stay internal.\nexport { createFramebuffer, createTexture } from './utils'\n\n/**********************************************************************************/\n/* */\n/* To ID */\n/* */\n/**********************************************************************************/\n\nlet index = 0\nconst PREFIX = 'VIEW_GL_ALIAS'\n// Firefox has currently a bug where it can not handle symbol as WeakRef / key for WeakMap\n// see https://bugzilla.mozilla.org/show_bug.cgi?id=1710433\nconst HAS_WEAK_SYMBOL = (() => {\n try {\n const symbol = Symbol()\n new WeakMap().set(symbol, '')\n return true\n } catch {\n return false\n }\n})()\n// NOTE: fallback to Map will currently cause a minor memory leak.\nconst SYMBOL_MAP = createUpsertMap(HAS_WEAK_SYMBOL ? WeakMap<symbol, string> : Map<symbol, string>)\n\nexport function toID(key: string | number | symbol) {\n if (typeof key === 'string') {\n return key\n }\n if (typeof key === 'symbol') {\n return SYMBOL_MAP.getOrInsert(key, () => `${PREFIX}_${index++}`)\n }\n return key.toString()\n}\n\n/**********************************************************************************/\n/* */\n/* View */\n/* */\n/**********************************************************************************/\n\nexport function view<TSchema extends ViewSchema>(\n gl: GL,\n program: WebGLProgram,\n schema: TSchema,\n { signal }: ViewOptions = {},\n): View<TSchema> {\n // The sub-views are built without the signal and the view wires disposal\n // once, so that `dispose()` and aborting do the same thing rather than each\n // doing half of it.\n const attributes = !schema.attributes ? undefined : attributeView(gl, program, schema.attributes)\n const interleavedAttributes = !schema.interleavedAttributes\n ? undefined\n : interleavedAttributeView(gl, program, schema.interleavedAttributes)\n // Owned by the view, on the view's signal. This is the line the split was\n // really about: it used to read `bufferView(gl, schema.buffers)` with the\n // options dropped, so a view's buffers were the only resources that still\n // needed disposing by hand. That was a missing argument rather than a wrong\n // model — a buffer whose lifetime IS the view's belongs with it.\n const buffers = !schema.buffers ? undefined : bufferView(gl, schema.buffers)\n\n // Vertex arrays are made on demand rather than declared, so they are the one\n // thing the view cannot dispose from the schema alone. Held until disposed —\n // by the view or by the caller — and dropped either way, so a view that hands\n // out an array per frame does not accumulate them.\n const vertexArrays = new Set<VertexArrayMethods>()\n\n const dispose = once(() => {\n if (attributes) forEachObject(attributes, value => value.dispose())\n if (interleavedAttributes) forEachObject(interleavedAttributes, value => value.dispose())\n if (buffers) forEachObject(buffers, value => value.dispose())\n vertexArrays.forEach(vertexArray => vertexArray.dispose())\n vertexArrays.clear()\n })\n\n signal?.addEventListener('abort', dispose)\n\n return {\n uniforms: !schema.uniforms ? undefined : uniformView(gl, program, schema.uniforms),\n attributes,\n interleavedAttributes,\n buffers,\n vao(participants: VertexArrayParticipant[]) {\n const vertexArray = vaoView(gl, participants)\n vertexArrays.add(vertexArray)\n return {\n ...vertexArray,\n dispose: once(() => {\n vertexArrays.delete(vertexArray)\n vertexArray.dispose()\n }),\n }\n },\n dispose,\n } as View<TSchema>\n}\n\n/**********************************************************************************/\n/* */\n/* Vertex Array */\n/* */\n/**********************************************************************************/\n\n/**\n * Bind the default vertex array, returning a disposer that puts the previous\n * one back. The pointer calls name no destination, so anything applied without\n * a vertex array of its own has to say which one it means — and a vertex array\n * keeps what it is given, so writing into a caller's array by accident would\n * outlive the call that did it.\n */\nfunction bindDefaultVertexArray(gl: GL): () => void {\n const feature = getVertexArrayObject(gl)\n if (!feature) {\n return () => {}\n }\n const previous = gl.getParameter(VERTEX_ARRAY_BINDING) as WebGLVertexArrayObject | null\n feature.bindVertexArray(null)\n return () => feature.bindVertexArray(previous)\n}\n\n/**\n * A vertex array over the participants one draw needs.\n *\n * Where the context has vertex arrays, each participant writes itself in once,\n * here, and `bind()` is a single `bindVertexArray`. Where it does not — WebGL1\n * without `OES_vertex_array_object` — there is nowhere to keep the state, so\n * `bind()` re-applies every participant and the disposer puts back what they\n * displaced. Same contract, and the emulation is why the name still fits.\n */\nexport function vaoView(\n gl: GL,\n participants: VertexArrayParticipant[],\n { signal }: ViewOptions = {},\n): VertexArrayMethods {\n const feature = getVertexArrayObject(gl)\n\n const methods: VertexArrayMethods = !feature\n ? {\n bind() {\n const restores = participants.map(participant => participant.applyToVertexArray())\n participants.forEach(participant => participant.applyToContext?.())\n return once(() => restores.forEach(restore => restore()))\n },\n unbind() {},\n dispose() {},\n }\n : (() => {\n const vertexArray = assertedNotNullish(feature.createVertexArray())\n const previous = gl.getParameter(VERTEX_ARRAY_BINDING) as WebGLVertexArrayObject | null\n feature.bindVertexArray(vertexArray)\n // Discarding the restorers is the point: the state lives in this array\n // now, and the array is thrown away whole.\n for (const participant of participants) {\n participant.applyToVertexArray()\n }\n feature.bindVertexArray(previous)\n\n return {\n bind() {\n const previousVertexArray = gl.getParameter(\n VERTEX_ARRAY_BINDING,\n ) as WebGLVertexArrayObject | null\n feature.bindVertexArray(vertexArray)\n // Context state the array cannot hold — see applyToContext.\n participants.forEach(participant => participant.applyToContext?.())\n return once(() => feature.bindVertexArray(previousVertexArray))\n },\n unbind() {\n feature.bindVertexArray(null)\n },\n dispose: once(() => feature.deleteVertexArray(vertexArray)),\n }\n })()\n\n signal?.addEventListener('abort', () => methods.dispose())\n\n return methods\n}\n\n/**********************************************************************************/\n/* */\n/* Uniform View */\n/* */\n/**********************************************************************************/\n\nexport function uniformView<T extends UniformSchema>(\n gl: GL,\n program: WebGLProgram,\n schema: T,\n): InferUniformView<T> {\n // @ts-expect-error - conditional return type based on size is hard to infer\n return mapObject(schema, ({ kind, size }, key) => {\n const name = toID(key)\n\n if (isSamplerKind(kind)) {\n const location = gl.getUniformLocation(program, name)\n return {\n set(arg: number) {\n gl.uniform1i(location, arg)\n },\n }\n }\n\n // Array uniform - support both bulk set and indexed access\n if (size) {\n const bulkFnName = `uniform${kindToUniformFnName(kind)}v`\n // @ts-ignore FIX WEBGL/WEBGL2 TYPES\n const bulkFn = gl[bulkFnName].bind(gl)\n const bulkLocation = gl.getUniformLocation(program, name)\n\n const elementFnName = `uniform${kindToUniformFnName(kind)}`\n // @ts-ignore FIX WEBGL/WEBGL2 TYPES\n const elementFn = gl[elementFnName].bind(gl)\n\n // Build array of element setters\n const elements: Array<{ set(...args: any[]): void }> = []\n for (let i = 0; i < size; i++) {\n const location = gl.getUniformLocation(program, `${name}[${i}]`)\n elements[i] = {\n set(...args: any[]) {\n elementFn(location, ...args)\n },\n }\n }\n\n // Return array-like object with bulk set\n return Object.assign(elements, {\n set(arg: Float32Array) {\n bulkFn(bulkLocation, arg)\n },\n })\n }\n\n // Non-array uniform\n const location = gl.getUniformLocation(program, name)\n const fnName = `uniform${kindToUniformFnName(kind)}`\n\n // @ts-ignore FIX WEBGL/WEBGL2 TYPES\n const fn = gl[fnName].bind(gl)\n\n if (isMatKind(kind)) {\n return {\n set(...args: any[]) {\n fn(location, false, args[0])\n },\n }\n }\n\n return {\n set(...args: any[]) {\n fn(location, ...args)\n },\n }\n })\n}\n\n/**********************************************************************************/\n/* */\n/* Attribute View */\n/* */\n/**********************************************************************************/\n\ntype GLType =\n | 'FLOAT'\n | 'INT'\n | 'UNSIGNED_INT'\n | 'SHORT'\n | 'UNSIGNED_SHORT'\n | 'BYTE'\n | 'UNSIGNED_BYTE'\n\nconst FORMAT_TO_GL_TYPE: Record<AttributeFormat, GLType> = {\n float32: 'FLOAT',\n int32: 'INT',\n uint32: 'UNSIGNED_INT',\n int16: 'SHORT',\n uint16: 'UNSIGNED_SHORT',\n int8: 'BYTE',\n uint8: 'UNSIGNED_BYTE',\n}\n\nconst FORMAT_BYTE_SIZE: Record<AttributeFormat, number> = {\n float32: 4,\n int32: 4,\n uint32: 4,\n int16: 2,\n uint16: 2,\n int8: 1,\n uint8: 1,\n}\n\nfunction defaultFormat(kind: AttributeKind): AttributeFormat {\n if (kind.startsWith('u')) return 'uint32'\n if (kind.startsWith('i')) return 'int32'\n return 'float32'\n}\n\n// Shared attribute helper functions\n// between attributeView and interleavedAttributeView\nfunction handleAttribute(\n gl: GL,\n location: number,\n size: number,\n stride: number,\n offset: number,\n glType: GLType,\n isIntegerKind: boolean,\n normalized: boolean,\n instanced?: boolean,\n) {\n gl.enableVertexAttribArray(location)\n if (isIntegerKind) {\n ;(gl as WebGL2RenderingContext).vertexAttribIPointer(location, size, gl[glType], stride, offset)\n } else {\n gl.vertexAttribPointer(location, size, gl[glType], normalized, stride, offset)\n }\n\n // Always stated, never inherited: the divisor belongs to the location rather\n // than to the program, so a location left at 1 by an earlier instanced\n // attribute would feed one value to every vertex here.\n // Get instanced-arrays-feature: extension if webgl, gl if webgl2\n const instancedArrays = getInstancedArrays(gl)\n if (instanced) {\n assertedNotNullish(instancedArrays).vertexAttribDivisor(location, 1)\n } else if (instancedArrays) {\n instancedArrays.vertexAttribDivisor(location, 0)\n }\n}\n\n// Same enum in webgl2 and in the webgl1 extensions, which expose no constants\nconst VERTEX_ATTRIB_ARRAY_DIVISOR = 0x88fe\nconst VERTEX_ARRAY_BINDING = 0x85b5\n\n// Reads the divisor currently attached to a location, 0 where instancing is\n// unavailable and nothing can have set one\nfunction readDivisor(gl: GL, location: number): number {\n return getInstancedArrays(gl)\n ? (gl.getVertexAttrib(location, VERTEX_ATTRIB_ARRAY_DIVISOR) as number)\n : 0\n}\n\nexport function attributeView<T extends AttributeSchema>(\n gl: GL,\n program: WebGLProgram,\n schema: T,\n { signal }: ViewOptions = {},\n): AttributeView<T> {\n const attributes = mapObject(\n schema,\n (\n { kind, format, normalized = false, instanced, buffer: providedBuffer },\n key,\n ): AttributeMethods => {\n const name = toID(key)\n\n // Whoever made the buffer deletes it. A schema can name a buffer that\n // belongs to another view — the quad `compile.toQuad` shares across every\n // program on a context, an attribute two programs step over — and\n // deleting one of those would take it out from under its owner.\n const buffer = providedBuffer ?? assertedNotNullish(gl.createBuffer())\n\n const location = gl.getAttribLocation(program, name)\n if (location < 0) {\n throw new Error(`Attribute '${name}' not found`)\n }\n\n const size = kindToSize(kind)\n const resolvedFormat = format ?? defaultFormat(kind)\n const glType = FORMAT_TO_GL_TYPE[resolvedFormat]\n const isIntKind = kind.startsWith('i') || kind.startsWith('u')\n\n function applyToVertexArray() {\n // Snapshot before the change, restore in the disposer\n const previousDivisor = readDivisor(gl, location)\n // vertexAttribPointer captures whatever is bound to ARRAY_BUFFER when\n // it runs, so this binding is the setup for the pointer, not a lasting\n // part of the vertex array's state.\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n handleAttribute(gl, location, size, 0, 0, glType, isIntKind, normalized, instanced)\n return once(() => {\n getInstancedArrays(gl)?.vertexAttribDivisor(location, previousDivisor)\n })\n }\n\n return {\n buffer,\n applyToVertexArray,\n bind() {\n const restoreVertexArray = bindDefaultVertexArray(gl)\n const restore = applyToVertexArray()\n return once(() => {\n restore()\n restoreVertexArray()\n })\n },\n dispose: once(() => {\n if (!providedBuffer) {\n gl.deleteBuffer(buffer)\n }\n }),\n set(data, usage = 'STATIC_DRAW') {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n gl.bufferData(gl.ARRAY_BUFFER, data, gl[usage])\n return this\n },\n }\n },\n )\n\n signal?.addEventListener('abort', function dispose() {\n forEachObject(attributes, value => value.dispose())\n })\n\n return attributes\n}\n\n/**********************************************************************************/\n/* */\n/* Interleaved Attribute View */\n/* */\n/**********************************************************************************/\n\n/**\n * The other place an attribute's value can come from: not a buffer, but the\n * context's current generic vertex attribute values, which an attribute reads\n * for every vertex when its array is disabled.\n *\n * A constant is a uniform in all but name — one value for the whole draw, set\n * by a function chosen from the kind — so it gets the setters a uniform gets,\n * off the same layout the buffer source uses.\n *\n * `vertexAttrib*` tops out at four floats and has no matrix form, so a layout\n * key that is fine in a buffer can be impossible as a constant. That is a hard\n * limit of the API rather than a choice, and it is worth saying so out loud at\n * the point someone reaches for it.\n */\nfunction constantSource(gl: GL, layout: InterleavedAttributeLayout[], locations: number[]) {\n const setters = layout.map((entry, index) => {\n const size = kindToSize(entry.kind)\n const name = toID(entry.key)\n if (isMatKind(entry.kind) || size > 4) {\n throw new Error(\n `'${name}' is a ${entry.kind}, which cannot be a constant attribute: vertexAttrib* takes at most 4 floats and has no matrix form. Use the buffer source for it.`,\n )\n }\n // The values are context state, not vertex-array state, so they are held\n // here and written again on every bind — see applyToContext.\n let values: number[] = []\n const fn = gl[`vertexAttrib${size as 1 | 2 | 3 | 4}f`].bind(gl)\n return {\n name,\n location: locations[index]!,\n write: () => {\n if (values.length) {\n ;(fn as (location: number, ...args: number[]) => void)(locations[index]!, ...values)\n }\n },\n methods: {\n set(...args: number[]) {\n values = args\n },\n },\n }\n })\n\n return Object.assign(Object.fromEntries(setters.map(setter => [setter.name, setter.methods])), {\n applyToVertexArray() {\n const restores = setters.map(({ location }) => {\n const wasEnabled = gl.getVertexAttrib(location, gl.VERTEX_ATTRIB_ARRAY_ENABLED) as boolean\n gl.disableVertexAttribArray(location)\n return () => (wasEnabled ? gl.enableVertexAttribArray(location) : undefined)\n })\n return once(() => restores.forEach(restore => restore()))\n },\n applyToContext() {\n setters.forEach(setter => setter.write())\n },\n bind() {\n const restoreVertexArray = bindDefaultVertexArray(gl)\n const restore = this.applyToVertexArray()\n this.applyToContext()\n return once(() => {\n restore()\n restoreVertexArray()\n })\n },\n })\n}\n\nexport function interleavedAttributeView<T extends InterleavedAttributeSchema>(\n gl: GL,\n program: WebGLProgram,\n schema: T,\n { signal }: ViewOptions = {},\n): InterleavedAttributeView<T> {\n // Initialize interleaved attributes\n const interleavedAttributes = mapObject(schema, ({ layout }) => {\n // Increment number to keep track of offset\n let index = 0\n\n // Calculate layout information\n const locations: number[] = []\n const handles = layout.map(layout => {\n const name = toID(layout.key)\n\n const location = gl.getAttribLocation(program, name)\n\n if (location < 0) {\n throw new Error(`Attribute '${name}' not found`)\n }\n\n locations.push(location)\n\n const size = kindToSize(layout.kind)\n const offset = index\n const resolvedFormat = layout.format ?? defaultFormat(layout.kind)\n const glType = FORMAT_TO_GL_TYPE[resolvedFormat]\n const isIntKind = layout.kind.startsWith('i') || layout.kind.startsWith('u')\n const normalized = layout.normalized ?? false\n index += size * FORMAT_BYTE_SIZE[resolvedFormat]\n\n return (divisor: 0 | 1) =>\n handleAttribute(\n gl,\n location,\n size,\n stride,\n offset,\n glType,\n isIntKind,\n normalized,\n divisor === 1,\n )\n })\n\n // Set stride to final index\n const stride = index\n\n // Create a buffer\n const buffer = assertedNotNullish(gl.createBuffer())\n\n // This layout used to create a vertex array of its own, here, which is why\n // the other participants in a draw had to be bound after it to be included\n // — the array they landed in was whichever one happened to be current.\n // Arrays are `vao()`'s job now; a layout is a layout and a buffer.\n function applyToVertexArray(divisor: 0 | 1) {\n const previousDivisors = locations.map(\n location => [location, readDivisor(gl, location)] as const,\n )\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n for (const handle of handles) {\n handle(divisor)\n }\n return once(() => {\n const instancedArrays = getInstancedArrays(gl)\n previousDivisors.forEach(([location, previous]) => {\n instancedArrays?.vertexAttribDivisor(location, previous)\n })\n })\n }\n\n let constant: ReturnType<typeof constantSource> | undefined\n\n /** One layout, one buffer, but a divisor per draw rather than per schema. */\n function bufferSource(divisor: 0 | 1) {\n const apply = () => applyToVertexArray(divisor)\n return {\n applyToVertexArray: apply,\n bind() {\n const restoreVertexArray = bindDefaultVertexArray(gl)\n const restore = apply()\n return once(() => {\n restore()\n restoreVertexArray()\n })\n },\n }\n }\n\n return {\n buffer: Object.assign(bufferSource(0), {\n /** The same buffer, stepped once per instance instead of once per vertex. */\n perInstance: bufferSource(1),\n set(value: Float32Array, usage: GLUsage = 'STATIC_DRAW') {\n // Uploading is storage, not binding: ARRAY_BUFFER is not vertex-array\n // state, so this touches no array, whichever one is bound.\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n gl.bufferData(gl.ARRAY_BUFFER, value, gl[usage])\n },\n allocate(length: number, usage: GLUsage = 'STATIC_DRAW') {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n gl.bufferData(gl.ARRAY_BUFFER, length * Float32Array.BYTES_PER_ELEMENT, gl[usage])\n },\n write(data: Float32Array, offset: number) {\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n gl.bufferSubData(gl.ARRAY_BUFFER, offset * Float32Array.BYTES_PER_ELEMENT, data)\n },\n }),\n // Lazy: a layout key can be perfectly good in a buffer and impossible as\n // a constant, and finding that out should wait until someone asks for one.\n get constant() {\n return (constant ??= constantSource(gl, layout, locations))\n },\n dispose: once(() => gl.deleteBuffer(buffer)),\n } satisfies InterleavedAttributeMethods\n })\n\n signal?.addEventListener('abort', function dispose() {\n forEachObject(interleavedAttributes, value => value.dispose())\n })\n\n return interleavedAttributes\n}\n\n/**********************************************************************************/\n/* */\n/* Buffer View */\n/* */\n/**********************************************************************************/\n\nexport function bufferView<T extends BufferSchema>(\n gl: GL,\n schema: T,\n { signal }: ViewOptions = {},\n): BufferView<T> {\n // Initialize buffers\n const buffers = mapObject(schema, ({ target = 'ARRAY_BUFFER', usage = 'STATIC_DRAW' }) => {\n const buffer = assertedNotNullish(gl.createBuffer())\n\n function applyToVertexArray() {\n // Snapshot before the change, restore in the disposer. Restoring the\n // previous buffer rather than null matters for ELEMENT_ARRAY_BUFFER,\n // whose binding is recorded in the bound vertex array: clearing it\n // would strip the index buffer from an array the caller may not own.\n const previousBuffer = gl.getParameter(gl[`${target}_BINDING`]) as WebGLBuffer | null\n gl.bindBuffer(gl[target], buffer)\n return once(() => {\n gl.bindBuffer(gl[target], previousBuffer)\n })\n }\n\n return {\n applyToVertexArray,\n bind() {\n // ELEMENT_ARRAY_BUFFER's binding belongs to the bound vertex array, so\n // like the attributes this has to say which array it means. ARRAY_BUFFER\n // is context state and unaffected either way.\n const restoreVertexArray = bindDefaultVertexArray(gl)\n const restore = applyToVertexArray()\n return once(() => {\n restore()\n restoreVertexArray()\n })\n },\n dispose: once(() => gl.deleteBuffer(buffer)),\n set(data: Float32Array) {\n gl.bindBuffer(gl[target], buffer)\n gl.bufferData(gl[target], data, gl[usage])\n },\n }\n })\n\n signal?.addEventListener('abort', function dispose() {\n forEachObject(buffers, value => value.dispose())\n })\n\n return buffers\n}\n"],"mappings":"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","names":["location","index","layout"]}
package/dist/gl.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { G as GL, V as ViewOptions, R as RemoveSuffix } from './types-k1Xz1iO3.mjs';
1
+ import { G as GL, V as ViewOptions, R as RemoveSuffix } from './types-Dar3fLfd.mjs';
2
2
 
3
3
  /**********************************************************************************/
4
4
  /**********************************************************************************/
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { G as GL, F as FramebufferDefinition, V as ViewOptions, T as TextureDefinition, a as ViewSchema, b as View, c as VertexArrayParticipant, d as VertexArrayMethods, U as UniformSchema, e as UniformView, A as AttributeSchema, f as AttributeView, I as InterleavedAttributeSchema, g as InterleavedAttributeView, B as BufferSchema, h as BufferView } from './types-k1Xz1iO3.mjs';
2
- export { D as AttributeDefinition, C as AttributeFormat, z as AttributeKind, E as AttributeMethods, y as AttributeShortHand, ac as AttributeToken, ad as AttributeTokenFn, P as BufferDefinition, Q as BufferMethods, L as BufferSource, ak as CompileResult, M as ConstantAttributeMethods, N as ConstantSource, ai as FlattenSlots, a3 as Format, W as Framebuffer, a9 as GLSL, a7 as GLSLResult, a8 as GLSLSlot, ah as GLSLSlotsToSchema, af as GLSLToSchema, ag as GLSLToView, i as GLTarget, n as GLTextureFilter, l as GLTextureFormat, k as GLTextureTarget, m as GLTextureType, o as GLTextureWrap, j as GLUsage, ae as InterleaveToken, J as InterleavedAttributeDefinition, H as InterleavedAttributeLayout, O as InterleavedAttributeMethods, a2 as InternalFormat, p as KIND_TO_SIZE_MAP, K as KIND_TO_UNIFORM_FN_NAME_MAP, aj as MergeGLSLSchema, a4 as PixelType, S as Source, a5 as TexImage2DOptions, Z as TextureMethods, $ as TextureParameterName, a0 as TextureParameterValue, a1 as TextureParameters, Y as TextureSchema, X as TextureTarget, _ as TextureView, v as UniformArrayMethods, t as UniformDefinition, u as UniformElementMethods, q as UniformFnName, r as UniformKind, s as UniformKindMap, w as UniformMethods, aa as UniformToken, ab as UniformTokenFn, x as UniformValue, a6 as ViewSchemaPartial } from './types-k1Xz1iO3.mjs';
1
+ import { G as GL, F as FramebufferDefinition, V as ViewOptions, T as TextureDefinition, a as ViewSchema, b as View, c as VertexArrayParticipant, d as VertexArrayMethods, U as UniformSchema, e as UniformView, A as AttributeSchema, f as AttributeView, I as InterleavedAttributeSchema, g as InterleavedAttributeView, B as BufferSchema, h as BufferView } from './types-Dar3fLfd.mjs';
2
+ export { D as AttributeDefinition, C as AttributeFormat, z as AttributeKind, E as AttributeMethods, y as AttributeShortHand, ac as AttributeToken, ad as AttributeTokenFn, P as BufferDefinition, Q as BufferMethods, L as BufferSource, ak as CompileResult, M as ConstantAttributeMethods, N as ConstantSource, ai as FlattenSlots, a3 as Format, W as Framebuffer, a9 as GLSL, a7 as GLSLResult, a8 as GLSLSlot, ah as GLSLSlotsToSchema, af as GLSLToSchema, ag as GLSLToView, i as GLTarget, n as GLTextureFilter, l as GLTextureFormat, k as GLTextureTarget, m as GLTextureType, o as GLTextureWrap, j as GLUsage, ae as InterleaveToken, J as InterleavedAttributeDefinition, H as InterleavedAttributeLayout, O as InterleavedAttributeMethods, a2 as InternalFormat, p as KIND_TO_SIZE_MAP, K as KIND_TO_UNIFORM_FN_NAME_MAP, aj as MergeGLSLSchema, a4 as PixelType, S as Source, a5 as TexImage2DOptions, Z as TextureMethods, $ as TextureParameterName, a0 as TextureParameterValue, a1 as TextureParameters, Y as TextureSchema, X as TextureTarget, _ as TextureView, v as UniformArrayMethods, t as UniformDefinition, u as UniformElementMethods, q as UniformFnName, r as UniformKind, s as UniformKindMap, w as UniformMethods, aa as UniformToken, ab as UniformTokenFn, x as UniformValue, a6 as ViewSchemaPartial } from './types-Dar3fLfd.mjs';
3
3
 
4
4
  /**********************************************************************************/
5
5
  /**********************************************************************************/
package/dist/index.mjs CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  uniformView,
7
7
  vaoView,
8
8
  view
9
- } from "./chunk-H56LJYS5.mjs";
9
+ } from "./chunk-H4K75BIR.mjs";
10
10
  import {
11
11
  createFramebuffer,
12
12
  createTexture
package/dist/tag.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a8 as GLSLSlot, a9 as GLSL, ab as UniformTokenFn, ad as AttributeTokenFn, ac as AttributeToken, z as AttributeKind, D as AttributeDefinition, ae as InterleaveToken, a6 as ViewSchemaPartial, ak as CompileResult, al as Prettify, af as GLSLToSchema, G as GL } from './types-k1Xz1iO3.mjs';
1
+ import { a8 as GLSLSlot, a9 as GLSL, ab as UniformTokenFn, ad as AttributeTokenFn, ac as AttributeToken, z as AttributeKind, D as AttributeDefinition, ae as InterleaveToken, a6 as ViewSchemaPartial, ak as CompileResult, al as Prettify, af as GLSLToSchema, G as GL } from './types-Dar3fLfd.mjs';
2
2
 
3
3
  declare function glsl<TSlot extends GLSLSlot, const TSlots extends TSlot[]>(template: TemplateStringsArray, ...slots: [...TSlots]): GLSL<TSlots>;
4
4
  declare const uniform: {
package/dist/tag.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  toID,
3
3
  view
4
- } from "./chunk-H56LJYS5.mjs";
4
+ } from "./chunk-H4K75BIR.mjs";
5
5
  import {
6
6
  createProgram,
7
7
  createUpsertMap,
@@ -302,6 +302,13 @@ interface BufferSource extends Source {
302
302
  */
303
303
  perInstance: Source;
304
304
  set(data: Float32Array, usage?: GLUsage): void;
305
+ /** Sizes the buffer to `length` floats, contents undefined, discarding what it held. */
306
+ allocate(length: number, usage?: GLUsage): void;
307
+ /**
308
+ * Overwrites the floats from `offset` on with `data`, leaving the rest as it
309
+ * is. The range must fit inside the buffer's current size.
310
+ */
311
+ write(data: Float32Array, offset: number): void;
305
312
  }
306
313
  interface ConstantAttributeMethods {
307
314
  set(...values: number[]): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bigmistqke/view.gl",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "👀 Utilities for managing WebGL resources.",
5
5
  "exports": {
6
6
  ".": {
@@ -16,11 +16,26 @@
16
16
  "types": "./dist/gl.d.mts"
17
17
  }
18
18
  },
19
+ "scripts": {
20
+ "build": "tsup",
21
+ "bump": "bumpp",
22
+ "dev:build": "vite build dev",
23
+ "dev:preview": "vite preview dev",
24
+ "dev:watch": "concurrently \"pnpm dev:preview\" \"vite dev:build --watch\"",
25
+ "dev": "vite serve dev",
26
+ "format": "prettier -w \"src/**/*.{js,ts,json,css,tsx,jsx}\" \"dev/**/*.{js,ts,json,css,tsx,jsx}\"",
27
+ "lint:types": "tsc --noEmit",
28
+ "prepublish": "pnpm test && pnpm build",
29
+ "test:coverage": "vitest run --coverage",
30
+ "test:ui": "vitest --ui",
31
+ "test": "vitest --run"
32
+ },
19
33
  "keywords": [
20
34
  "WebGL"
21
35
  ],
22
36
  "author": "",
23
37
  "license": "ISC",
38
+ "packageManager": "pnpm@10.5.1",
24
39
  "devDependencies": {
25
40
  "@vitest/ui": "^3.2.4",
26
41
  "bumpp": "^10.4.0",
@@ -32,19 +47,5 @@
32
47
  "vite": "^7.0.2",
33
48
  "vite-tsconfig-paths": "^5.1.4",
34
49
  "vitest": "^3.2.4"
35
- },
36
- "scripts": {
37
- "build": "tsup",
38
- "bump": "bumpp",
39
- "dev:build": "vite build dev",
40
- "dev:preview": "vite preview dev",
41
- "dev:watch": "concurrently \"pnpm dev:preview\" \"vite dev:build --watch\"",
42
- "dev": "vite serve dev",
43
- "format": "prettier -w \"src/**/*.{js,ts,json,css,tsx,jsx}\" \"dev/**/*.{js,ts,json,css,tsx,jsx}\"",
44
- "lint:types": "tsc --noEmit",
45
- "prepublish": "pnpm test && pnpm build",
46
- "test:coverage": "vitest run --coverage",
47
- "test:ui": "vitest --ui",
48
- "test": "vitest --run"
49
50
  }
50
- }
51
+ }
package/src/index.ts CHANGED
@@ -622,6 +622,14 @@ export function interleavedAttributeView<T extends InterleavedAttributeSchema>(
622
622
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
623
623
  gl.bufferData(gl.ARRAY_BUFFER, value, gl[usage])
624
624
  },
625
+ allocate(length: number, usage: GLUsage = 'STATIC_DRAW') {
626
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
627
+ gl.bufferData(gl.ARRAY_BUFFER, length * Float32Array.BYTES_PER_ELEMENT, gl[usage])
628
+ },
629
+ write(data: Float32Array, offset: number) {
630
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
631
+ gl.bufferSubData(gl.ARRAY_BUFFER, offset * Float32Array.BYTES_PER_ELEMENT, data)
632
+ },
625
633
  }),
626
634
  // Lazy: a layout key can be perfectly good in a buffer and impossible as
627
635
  // a constant, and finding that out should wait until someone asks for one.
package/src/types.ts CHANGED
@@ -424,6 +424,13 @@ export interface BufferSource extends Source {
424
424
  */
425
425
  perInstance: Source
426
426
  set(data: Float32Array, usage?: GLUsage): void
427
+ /** Sizes the buffer to `length` floats, contents undefined, discarding what it held. */
428
+ allocate(length: number, usage?: GLUsage): void
429
+ /**
430
+ * Overwrites the floats from `offset` on with `data`, leaving the rest as it
431
+ * is. The range must fit inside the buffer's current size.
432
+ */
433
+ write(data: Float32Array, offset: number): void
427
434
  }
428
435
 
429
436
  export interface ConstantAttributeMethods {
@@ -959,6 +959,25 @@ describe('interleavedAttributeView', () => {
959
959
  expect(gl.vertexAttribDivisor).toHaveBeenCalledWith(expect.any(Number), 0)
960
960
  })
961
961
 
962
+ it('sizes the buffer without data, then fills it in parts', () => {
963
+ const schema = {
964
+ instanceData: { layout: [{ key: 'a_instancePos', kind: 'vec3' }] },
965
+ } satisfies InterleavedAttributeSchema
966
+
967
+ const { buffer } = interleavedAttributeView(gl, program, schema).instanceData
968
+ const target = vi.mocked(gl.createBuffer).mock.results.at(-1)!.value
969
+
970
+ buffer.allocate(12, 'DYNAMIC_DRAW')
971
+ expect(gl.bindBuffer).toHaveBeenLastCalledWith(gl.ARRAY_BUFFER, target)
972
+ expect(gl.bufferData).toHaveBeenLastCalledWith(gl.ARRAY_BUFFER, 48, gl.DYNAMIC_DRAW)
973
+
974
+ vi.mocked(gl.bindBuffer).mockClear()
975
+ const part = new Float32Array([1, 2, 3])
976
+ buffer.write(part, 6)
977
+ expect(gl.bindBuffer).toHaveBeenLastCalledWith(gl.ARRAY_BUFFER, target)
978
+ expect(gl.bufferSubData).toHaveBeenLastCalledWith(gl.ARRAY_BUFFER, 24, part)
979
+ })
980
+
962
981
  it('should handle integer attributes in layout', () => {
963
982
  const schema = {
964
983
  data: {
@@ -95,6 +95,7 @@ export function createMockGL() {
95
95
  }),
96
96
 
97
97
  bufferData: vi.fn(),
98
+ bufferSubData: vi.fn(),
98
99
 
99
100
  // Program methods
100
101
  createProgram: vi.fn(() => {