@solidrt/flux-types 0.0.50 → 0.0.52
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 +3 -3
- package/gui/audio.d.ts +116 -12
- package/gui/camera.d.ts +4 -3
- package/gui/gpu.d.ts +185 -28
- package/gui/rendertree.d.ts +90 -7
- package/gui/spatial.d.ts +188 -0
- package/index.d.ts +5 -1
- package/modules/fs.d.ts +33 -0
- package/modules/http.d.ts +3 -3
- package/modules/isolate.d.ts +50 -10
- package/modules/net.d.ts +2 -0
- package/modules/process.d.ts +36 -0
- package/modules/sqlite.d.ts +27 -5
- package/modules/subprocess.d.ts +9 -0
- package/modules/tty.d.ts +69 -0
- package/package.json +2 -1
- package/standards/abort.d.ts +36 -0
- package/standards/crypto.d.ts +18 -0
- package/standards/fetch.d.ts +8 -1
- package/standards/time.d.ts +21 -16
package/README.md
CHANGED
|
@@ -46,12 +46,12 @@ rely on must be named.
|
|
|
46
46
|
|
|
47
47
|
- `Flux` global (`version`, `capabilities`).
|
|
48
48
|
- `flux:*` modules: `flux:http`, `flux:fs`, `flux:sqlite`, `flux:subprocess`,
|
|
49
|
-
`flux:p2p`, `flux:net`, `flux:mdns`, `flux:process`, `flux:path`, `flux:wasm`, `flux:ffi`,
|
|
49
|
+
`flux:p2p`, `flux:net`, `flux:mdns`, `flux:process`, `flux:tty`, `flux:path`, `flux:wasm`, `flux:ffi`,
|
|
50
50
|
and (on a gui-enabled runtime)
|
|
51
|
-
`flux:camera`, `flux:microphone`, `flux:audio`, `flux:gpu`.
|
|
51
|
+
`flux:camera`, `flux:microphone`, `flux:audio`, `flux:gpu`, `flux:spatial`.
|
|
52
52
|
- Web-standard globals: `console`, `fetch` + `Headers`/`Request`/`Response`,
|
|
53
53
|
`setTimeout`/`setInterval`/`queueMicrotask`, `performance`, `WebSocket`,
|
|
54
|
-
`TextEncoder`/`TextDecoder`. These are deliberate subsets matching exactly what
|
|
54
|
+
`TextEncoder`/`TextDecoder`, `crypto.subtle.digest`. These are deliberate subsets matching exactly what
|
|
55
55
|
the runtime implements.
|
|
56
56
|
- GUI globals (gui-enabled runtime only): `requestAnimationFrame` /
|
|
57
57
|
`cancelAnimationFrame` (web-standard names, so kept global).
|
package/gui/audio.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
// Sound playback (gui-enabled runtime only
|
|
2
|
-
//
|
|
3
|
-
// a
|
|
4
|
-
//
|
|
1
|
+
// Sound playback (gui-enabled runtime only: feature-detect with
|
|
2
|
+
// `Flux.capabilities.includes("audio")` before importing on a runtime that may
|
|
3
|
+
// lack it - a static import fails at module load there). The imperative
|
|
4
|
+
// primitive; `play` decodes and starts a clip in one call, while
|
|
5
|
+
// `load`/`loadPcm`/`stream` yield a Clip that starts cheap overlapping
|
|
6
|
+
// Playbacks. Handles carry controls bound to just that clip or playback, so
|
|
7
|
+
// raw ids never leave the runtime.
|
|
5
8
|
|
|
6
9
|
declare module "flux:audio" {
|
|
7
10
|
/** Options for {@link play} and {@link Clip.play}. */
|
|
@@ -16,31 +19,97 @@ declare module "flux:audio" {
|
|
|
16
19
|
* all, which for a mono clip is about 3 dB louder than `pan: 0`.
|
|
17
20
|
*/
|
|
18
21
|
pan?: number
|
|
22
|
+
/**
|
|
23
|
+
* Playback rate: 1.0 plays as loaded, higher is faster and higher-pitched,
|
|
24
|
+
* lower slower and deeper (a plain resample, no formant correction).
|
|
25
|
+
* Clamped to [0.01, 100]. Defaults to 1.0.
|
|
26
|
+
*/
|
|
27
|
+
rate?: number
|
|
28
|
+
/**
|
|
29
|
+
* Fade in from silence over this many milliseconds (sample-accurate).
|
|
30
|
+
* Defaults to 0 (start at full level).
|
|
31
|
+
*/
|
|
32
|
+
fadeInMs?: number
|
|
33
|
+
/**
|
|
34
|
+
* Name of the bus this playback belongs to, so `stop({ bus })` can stop
|
|
35
|
+
* the whole group at once. Buses are plain names created by use - no
|
|
36
|
+
* setup call, and (for now) no per-bus gain.
|
|
37
|
+
*/
|
|
38
|
+
bus?: string
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Options for the live setters ({@link Playback.setGain} and friends). */
|
|
42
|
+
type RampOptions = {
|
|
43
|
+
/**
|
|
44
|
+
* Reach the new value by ramping over this many milliseconds instead of
|
|
45
|
+
* jumping. Linear, stepped by the engine at control rate (about every
|
|
46
|
+
* 10 ms), so a fade stays smooth regardless of the app's frame rate. A
|
|
47
|
+
* later set on the same parameter takes over from the ramp's current
|
|
48
|
+
* value; omitted (or 0) sets immediately and cancels any ramp in flight.
|
|
49
|
+
*/
|
|
50
|
+
rampMs?: number
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Options for {@link Playback.stop} and the module-level {@link stop}. */
|
|
54
|
+
type StopOptions = {
|
|
55
|
+
/**
|
|
56
|
+
* Fade to silence over this many milliseconds before stopping
|
|
57
|
+
* (sample-accurate) instead of cutting immediately. The playback keeps
|
|
58
|
+
* playing while it fades; ended() turns true once the fade completes.
|
|
59
|
+
*/
|
|
60
|
+
fadeOutMs?: number
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Options for the module-level {@link stop}. */
|
|
64
|
+
type StopAllOptions = StopOptions & {
|
|
65
|
+
/**
|
|
66
|
+
* Stop only the playbacks on this bus (see {@link PlayOptions.bus})
|
|
67
|
+
* instead of everything.
|
|
68
|
+
*/
|
|
69
|
+
bus?: string
|
|
19
70
|
}
|
|
20
71
|
|
|
21
72
|
/** One playing instance of a clip, with live controls bound to it. */
|
|
22
73
|
type Playback = {
|
|
23
|
-
/**
|
|
24
|
-
|
|
74
|
+
/**
|
|
75
|
+
* Stop this playback. A no-op if it already finished. Stopping is not
|
|
76
|
+
* pausing: a stopped playback is gone for good, including a looping one -
|
|
77
|
+
* to silence it temporarily, ramp its gain to 0 instead.
|
|
78
|
+
*/
|
|
79
|
+
stop(options?: StopOptions): void
|
|
25
80
|
/**
|
|
26
81
|
* Change the volume while playing. A finite number >= 0; 1.0 is the clip's
|
|
27
82
|
* own level. A no-op after the playback finished.
|
|
28
83
|
*/
|
|
29
|
-
setGain(gain: number): void
|
|
84
|
+
setGain(gain: number, options?: RampOptions): void
|
|
30
85
|
/**
|
|
31
86
|
* Move the stereo position while playing (see {@link PlayOptions.pan}).
|
|
87
|
+
* A ramped set on a never-panned playback sweeps from center. A no-op
|
|
88
|
+
* after the playback finished.
|
|
89
|
+
*/
|
|
90
|
+
setPan(pan: number, options?: RampOptions): void
|
|
91
|
+
/**
|
|
92
|
+
* Change the playback rate while playing (see {@link PlayOptions.rate}) -
|
|
93
|
+
* a live rate sweep is how an engine revs or a doppler pass falls.
|
|
32
94
|
* A no-op after the playback finished.
|
|
33
95
|
*/
|
|
34
|
-
|
|
96
|
+
setRate(rate: number, options?: RampOptions): void
|
|
35
97
|
/** Whether playback finished, naturally or via {@link stop}. */
|
|
36
98
|
ended(): boolean
|
|
37
99
|
}
|
|
38
100
|
|
|
39
101
|
/** A loaded clip that can be played without re-decoding. */
|
|
40
102
|
type Clip = {
|
|
41
|
-
/**
|
|
103
|
+
/**
|
|
104
|
+
* Start a fresh overlapping playback of this clip. Throws once 256
|
|
105
|
+
* playbacks are live at once - a guard that turns a runaway play() loop
|
|
106
|
+
* into an error instead of a saturated mixer.
|
|
107
|
+
*/
|
|
42
108
|
play(options?: PlayOptions): Playback
|
|
43
|
-
/**
|
|
109
|
+
/**
|
|
110
|
+
* Release the clip. Playbacks already running keep going; `play()` after
|
|
111
|
+
* unloading throws.
|
|
112
|
+
*/
|
|
44
113
|
unload(): void
|
|
45
114
|
}
|
|
46
115
|
|
|
@@ -80,6 +149,41 @@ declare module "flux:audio" {
|
|
|
80
149
|
* playback; do not overlap a stream with itself. Call `unload()` when done.
|
|
81
150
|
*/
|
|
82
151
|
export function stream(source: ReturnType<typeof import("flux:fs").file>): Clip
|
|
83
|
-
/**
|
|
84
|
-
|
|
152
|
+
/**
|
|
153
|
+
* Stop every playing sound - or just one bus with `{ bus }` - fading it
|
|
154
|
+
* out first if asked. Stopping is not pausing: stopped playbacks (looping
|
|
155
|
+
* ones included) cannot be restarted - to silence a group temporarily,
|
|
156
|
+
* ramp gains to 0 instead.
|
|
157
|
+
*/
|
|
158
|
+
export function stop(options?: StopAllOptions): void
|
|
159
|
+
/**
|
|
160
|
+
* Scale the whole mix: every playing and future flux:audio playback, on top
|
|
161
|
+
* of per-playback gains (1.0 = unchanged, 0 = silence). A finite number
|
|
162
|
+
* >= 0; ramps like the per-playback setters. Resets to 1.0 when the app
|
|
163
|
+
* reloads.
|
|
164
|
+
*/
|
|
165
|
+
export function setMasterGain(gain: number, options?: RampOptions): void
|
|
166
|
+
/**
|
|
167
|
+
* Scale one bus (see {@link PlayOptions.bus}): a playback's audible level
|
|
168
|
+
* is its own gain x its bus's gain x the master gain, each layer set
|
|
169
|
+
* independently - none overwrites another. Applies to live and future
|
|
170
|
+
* playbacks on the bus, defaults to 1.0, resets to 1.0 when the app
|
|
171
|
+
* reloads, and ramps like the other gain setters.
|
|
172
|
+
*
|
|
173
|
+
* NOT IMPLEMENTED YET: calling this throws. Until it lands, keep the bus
|
|
174
|
+
* gain in the app and fold it into each voice's setGain - one ramped
|
|
175
|
+
* write per change:
|
|
176
|
+
*
|
|
177
|
+
* ```ts
|
|
178
|
+
* let musicGain = 0.3
|
|
179
|
+
* for (let v of musicVoices) v.setGain(voiceGain * musicGain, { rampMs: 200 })
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
export function setBusGain(bus: string, gain: number, options?: RampOptions): void
|
|
183
|
+
/**
|
|
184
|
+
* The mixer's output sample rate in Hz. Synthesize PCM at this rate and
|
|
185
|
+
* {@link loadPcm} feeds it to the mixer without a resample. Opens the audio
|
|
186
|
+
* device on first use, like the load and play calls.
|
|
187
|
+
*/
|
|
188
|
+
export function outputSampleRate(): number
|
|
85
189
|
}
|
package/gui/camera.d.ts
CHANGED
|
@@ -65,9 +65,10 @@ declare module "flux:camera" {
|
|
|
65
65
|
* if permission is denied, and resolves once the first frame is ready. On
|
|
66
66
|
* Linux a session that delivers neither within 10 seconds rejects with a
|
|
67
67
|
* timeout error and releases the device (a wedged capture backend would
|
|
68
|
-
* otherwise hold it and never settle).
|
|
69
|
-
*
|
|
70
|
-
*
|
|
68
|
+
* otherwise hold it and never settle). The first open also starts the
|
|
69
|
+
* camera subsystem and waits for it (on every platform, up to 10 seconds,
|
|
70
|
+
* then rejects with a timeout), so there is no need to poll listCameras
|
|
71
|
+
* before opening.
|
|
71
72
|
*/
|
|
72
73
|
export function open(options?: CameraOpenOptions): Promise<CameraSession>
|
|
73
74
|
/**
|
package/gui/gpu.d.ts
CHANGED
|
@@ -17,11 +17,12 @@
|
|
|
17
17
|
// they return.
|
|
18
18
|
//
|
|
19
19
|
// Sampling is a per-texture property declared at creation: every create path
|
|
20
|
-
// accepts `{ filter?, wrap? }` ("linear"/"nearest", "clamp"/"repeat"
|
|
21
|
-
// defaults linear + clamp for every origin). The state
|
|
22
|
-
// everywhere it is sampled - shader passes and `<texture>`
|
|
23
|
-
// and survives id-stable resizes. It cannot be changed after
|
|
24
|
-
//
|
|
20
|
+
// accepts `{ filter?, wrap?, mipmap? }` ("linear"/"nearest", "clamp"/"repeat",
|
|
21
|
+
// boolean; defaults linear + clamp + no mips for every origin). The state
|
|
22
|
+
// follows the id everywhere it is sampled - shader passes and `<texture>`
|
|
23
|
+
// display alike - and survives id-stable resizes. It cannot be changed after
|
|
24
|
+
// creation. `mipmap: true` keeps a mip chain on the id, regenerated after
|
|
25
|
+
// every upload or render, so shader sampling minifies without aliasing.
|
|
25
26
|
//
|
|
26
27
|
// Compositing several targets is a render-tree job, not a shader one: stack
|
|
27
28
|
// `<texture>` elements and set their `blendMode` (the full Skia set, e.g.
|
|
@@ -103,8 +104,9 @@ declare module "flux:gpu" {
|
|
|
103
104
|
* call site: a name with no active uniform, a value whose length does not
|
|
104
105
|
* fit the declared type, a `sampler2D` named here (samplers bind via
|
|
105
106
|
* `textures`), or a value that is not a number / number array throws.
|
|
106
|
-
*
|
|
107
|
-
*
|
|
107
|
+
* A uniform that is declared but optimized out by the compiler is accepted
|
|
108
|
+
* with a warning and the write is skipped, so one param object can drive
|
|
109
|
+
* shader variants that do not all use every uniform.
|
|
108
110
|
* An `undefined` value is skipped, so conditional spreads stay usable.
|
|
109
111
|
*/
|
|
110
112
|
export type ShaderParams = Record<string, number | number[]>
|
|
@@ -118,8 +120,29 @@ declare module "flux:gpu" {
|
|
|
118
120
|
* sampler2D inputs AND `<texture src>` display (a "nearest" texture
|
|
119
121
|
* upscales with hard pixels on screen - the pixel-art path). `wrap` only
|
|
120
122
|
* matters to shaders sampling outside 0..1; the display draw never tiles.
|
|
121
|
-
|
|
122
|
-
|
|
123
|
+
*
|
|
124
|
+
* `mipmap` (default false) keeps a mip chain on the id: rebuilt by the
|
|
125
|
+
* runtime after every upload (data textures) and every render (targets,
|
|
126
|
+
* automatically - nothing to schedule), and used by shader sampling when
|
|
127
|
+
* the texture is minified (trilinear for "linear", per-level nearest for
|
|
128
|
+
* "nearest"). Without it minification skips texels and aliases. Only
|
|
129
|
+
* shader sampling minifies through the chain; the `<texture>` display
|
|
130
|
+
* draw samples the full-size level. Regeneration is one GPU pass per
|
|
131
|
+
* upload or render, so a per-frame texture pays it per frame.
|
|
132
|
+
*/
|
|
133
|
+
export type SamplerOptions = { filter?: FilterMode; wrap?: WrapMode; mipmap?: boolean }
|
|
134
|
+
/**
|
|
135
|
+
* One `textures` binding value: a texture id, sampled with the texture's
|
|
136
|
+
* own declared state, or `{ id, filter?, wrap? }` to sample that id with a
|
|
137
|
+
* different filter and/or wrap in this binding only (blur a "nearest"
|
|
138
|
+
* atlas linearly; tile a clamped target in one consumer). The override is
|
|
139
|
+
* a per-pass deviation: the texture's own state stays what `<texture>`
|
|
140
|
+
* paints and what every binding without an override uses. `mipmap` is
|
|
141
|
+
* not overridable - the chain either exists on the id or it does not.
|
|
142
|
+
*/
|
|
143
|
+
export type TextureBinding = TextureId | { id: TextureId; filter?: FilterMode; wrap?: WrapMode }
|
|
144
|
+
/** Sampler2D inputs by uniform name; see {@link TextureBinding}. */
|
|
145
|
+
export type TextureBindings = Record<string, TextureBinding>
|
|
123
146
|
/**
|
|
124
147
|
* A free-form debug name every create accepts (WebGPU's label): surfaced by
|
|
125
148
|
* the dev server's GPU inventory (get_gpu_resources) and in engine log
|
|
@@ -243,7 +266,7 @@ declare module "flux:gpu" {
|
|
|
243
266
|
width: number,
|
|
244
267
|
height: number,
|
|
245
268
|
params?: ShaderParams | null,
|
|
246
|
-
opts?: { textures?:
|
|
269
|
+
opts?: { textures?: TextureBindings } & SamplerOptions & LabelOption,
|
|
247
270
|
): TextureId
|
|
248
271
|
/**
|
|
249
272
|
* Compile a single shader stage from raw GLSL ES: the primitive under
|
|
@@ -310,9 +333,16 @@ declare module "flux:gpu" {
|
|
|
310
333
|
* arithmetic. Declaring any makes `instanceBuffer` required on every
|
|
311
334
|
* entry drawn with this pipeline. A mat4 per instance is its four
|
|
312
335
|
* vec4 columns, reassembled in the shader (attributes have no matrix
|
|
313
|
-
* formats, as in WebGPU).
|
|
336
|
+
* formats, as in WebGPU). Instance N always reads record N of the
|
|
337
|
+
* entry's buffer, from record 0 (ES 3.0 has no base instance), so
|
|
338
|
+
* several independently culled groups cannot share one buffer as
|
|
339
|
+
* sub-ranges: give each group its own `instanceBuffer` and entry, and
|
|
340
|
+
* cull it by `instanceCount`. Each attribute's `slot` (default 0)
|
|
341
|
+
* picks a buffer of the entry's `instanceBuffers` list (see
|
|
342
|
+
* {@link InstanceAttribute}); a pipeline using only slot 0 binds via
|
|
343
|
+
* the plain `instanceBuffer` key.
|
|
314
344
|
*/
|
|
315
|
-
instanceAttributes?:
|
|
345
|
+
instanceAttributes?: InstanceAttribute[]
|
|
316
346
|
topology?: Topology
|
|
317
347
|
blend?: BlendMode
|
|
318
348
|
cull?: CullMode
|
|
@@ -364,6 +394,18 @@ declare module "flux:gpu" {
|
|
|
364
394
|
* read-modify-write of its own pixels (decay, blur, simulation) still
|
|
365
395
|
* ping-pongs across two manual targets - a pass can never sample the
|
|
366
396
|
* texture it writes.
|
|
397
|
+
*
|
|
398
|
+
* `samples` (1, 2, 4 or 8; default 1) multisamples the target's storage:
|
|
399
|
+
* edges of filled geometry get coverage-weighted AA instead of binary
|
|
400
|
+
* jaggies. Storage only - the texture id still names a single-sample
|
|
401
|
+
* image, so display, sampling, `readTexture` and `copyTexture` are
|
|
402
|
+
* unaffected. The count is clamped to the device maximum and a
|
|
403
|
+
* configuration the driver refuses falls back to single-sample with a
|
|
404
|
+
* warning (read the effective value off the resource inventory). Cannot
|
|
405
|
+
* combine with `loadOp: "load"` (throws): multisampled storage cannot
|
|
406
|
+
* load the previous contents. Tiled mobile GPUs resolve in-tile
|
|
407
|
+
* (EXT_multisampled_render_to_texture); everywhere else a resolve blit
|
|
408
|
+
* follows each pass.
|
|
367
409
|
*/
|
|
368
410
|
export function createShaderTarget(
|
|
369
411
|
pipeline: RenderPipelineId,
|
|
@@ -371,12 +413,16 @@ declare module "flux:gpu" {
|
|
|
371
413
|
height: number,
|
|
372
414
|
params?: ShaderParams | null,
|
|
373
415
|
opts?: {
|
|
374
|
-
textures?:
|
|
416
|
+
textures?: TextureBindings
|
|
375
417
|
buffer?: BufferId
|
|
376
418
|
instanceBuffer?: BufferId
|
|
419
|
+
/** One buffer per instance slot of the pipeline (index = the
|
|
420
|
+
* attributes' `slot`); pass this OR `instanceBuffer`, not both. */
|
|
421
|
+
instanceBuffers?: BufferId[]
|
|
377
422
|
clearColor?: [number, number, number, number]
|
|
378
423
|
render?: "auto" | "manual"
|
|
379
424
|
loadOp?: "clear" | "load"
|
|
425
|
+
samples?: 1 | 2 | 4 | 8
|
|
380
426
|
} & (DrawRange | (IndexBinding & IndexRange)) &
|
|
381
427
|
SamplerOptions &
|
|
382
428
|
LabelOption,
|
|
@@ -388,6 +434,16 @@ declare module "flux:gpu" {
|
|
|
388
434
|
* immediately.
|
|
389
435
|
*/
|
|
390
436
|
export function destroyProgram(id: ProgramId): void
|
|
437
|
+
/**
|
|
438
|
+
* The vertex attributes a linked program actually reads (name and format),
|
|
439
|
+
* as the compiler left them: an `in` the vertex stage never uses is not
|
|
440
|
+
* listed, and a type no layout can feed (a matrix, an integer vector) is
|
|
441
|
+
* rejected at linkProgram. This is the list a pipeline over the program
|
|
442
|
+
* must cover between `attributes` and `instanceAttributes` - an uncovered
|
|
443
|
+
* or mis-formatted one throws at createRenderPipeline. Answered locally,
|
|
444
|
+
* no GPU round trip.
|
|
445
|
+
*/
|
|
446
|
+
export function programAttributes(program: ProgramId): VertexAttribute[]
|
|
391
447
|
export type Topology = "points" | "lines" | "line-strip" | "triangles" | "triangle-strip"
|
|
392
448
|
/**
|
|
393
449
|
* Blending for a pipeline's own draw. "none" (default) overwrites:
|
|
@@ -439,6 +495,17 @@ declare module "flux:gpu" {
|
|
|
439
495
|
* shader's `in` declarations.
|
|
440
496
|
*/
|
|
441
497
|
export type VertexAttribute = { name: string; format: "f32" | "vec2" | "vec3" | "vec4" }
|
|
498
|
+
/**
|
|
499
|
+
* One float attribute of a per-instance record. `slot` (default 0) picks
|
|
500
|
+
* which buffer of the entry's `instanceBuffers` list the attribute
|
|
501
|
+
* fetches from: attributes sharing a slot interleave into one record in
|
|
502
|
+
* list order, distinct slots are distinct buffers with their own strides
|
|
503
|
+
* - which is what lets two writers own instance data independently (a
|
|
504
|
+
* core-written pose buffer beside an app-written style buffer). Slots
|
|
505
|
+
* must be dense from 0, at most 4; a single-slot pipeline (every `slot`
|
|
506
|
+
* omitted) binds via the plain `instanceBuffer` key.
|
|
507
|
+
*/
|
|
508
|
+
export type InstanceAttribute = VertexAttribute & { slot?: number }
|
|
442
509
|
/**
|
|
443
510
|
* A pipeline target's draw as data, WebGPU-style: `firstVertex` +
|
|
444
511
|
* `vertexCount` pick the vertex range `[firstVertex, firstVertex +
|
|
@@ -453,7 +520,9 @@ declare module "flux:gpu" {
|
|
|
453
520
|
* buffer bound, `instanceCount` is bounds-checked against it like every
|
|
454
521
|
* fetch (instances 0..N-1 each read one record). Two GL facts worth
|
|
455
522
|
* knowing: `gl_VertexID` includes `firstVertex` (as in WebGPU), and
|
|
456
|
-
* `gl_InstanceID` always counts from 0 - ES 3.0 has no base instance
|
|
523
|
+
* `gl_InstanceID` always counts from 0 - ES 3.0 has no base instance, so
|
|
524
|
+
* instance N reads record N of the entry's `instanceBuffer` and a group
|
|
525
|
+
* that is culled independently needs its own buffer and entry.
|
|
457
526
|
*/
|
|
458
527
|
export type DrawRange = { firstVertex?: number; vertexCount?: number; instanceCount?: number }
|
|
459
528
|
/**
|
|
@@ -486,6 +555,28 @@ declare module "flux:gpu" {
|
|
|
486
555
|
* there is no base vertex (ES 3.0, like ES 3.0's missing base instance).
|
|
487
556
|
*/
|
|
488
557
|
export type IndexRange = { firstIndex?: number; indexCount?: number; instanceCount?: number }
|
|
558
|
+
/**
|
|
559
|
+
* A draw entry's buffer swap: each key present re-points that role of the
|
|
560
|
+
* entry at another {@link createBuffer} buffer, absent keys keep their
|
|
561
|
+
* current buffer. Replace-only - the roles an entry fills are pipeline
|
|
562
|
+
* layout state (`attributes` needs a `buffer`, `instanceAttributes` an
|
|
563
|
+
* `instanceBuffer`) and indexing is its draw vocabulary, so naming a role
|
|
564
|
+
* the entry does not fill throws; `indexBuffer` travels with
|
|
565
|
+
* `indexFormat` as at create. The entry's current range is kept and
|
|
566
|
+
* rechecked against the new buffers' sizes: a swap to a buffer too small
|
|
567
|
+
* for the live range throws (shrink the range first); a larger buffer
|
|
568
|
+
* never does. This is the growth primitive: a population outgrowing its
|
|
569
|
+
* instance buffer creates a larger one, writes it, swaps, and destroys
|
|
570
|
+
* the old (the entry holds the old buffer alive until the swap lands, so
|
|
571
|
+
* either order is safe). `instanceBuffer` swaps slot 0;
|
|
572
|
+
* `instanceBuffers` swaps every slot at once and must fill exactly the
|
|
573
|
+
* slots the entry fills (pass one spelling or the other).
|
|
574
|
+
*/
|
|
575
|
+
export type BufferUpdate = {
|
|
576
|
+
buffer?: BufferId
|
|
577
|
+
instanceBuffer?: BufferId
|
|
578
|
+
instanceBuffers?: BufferId[]
|
|
579
|
+
} & ({} | IndexBinding)
|
|
489
580
|
|
|
490
581
|
/**
|
|
491
582
|
* Compile a GLSL ES vertex+fragment pipeline into an offscreen texture of
|
|
@@ -525,12 +616,15 @@ declare module "flux:gpu" {
|
|
|
525
616
|
height: number,
|
|
526
617
|
params?: ShaderParams | null,
|
|
527
618
|
opts?: {
|
|
528
|
-
textures?:
|
|
619
|
+
textures?: TextureBindings
|
|
529
620
|
attributes?: VertexAttribute[]
|
|
530
621
|
buffer?: BufferId
|
|
531
622
|
/** See {@link createRenderPipeline}'s `instanceAttributes`. */
|
|
532
|
-
instanceAttributes?:
|
|
623
|
+
instanceAttributes?: InstanceAttribute[]
|
|
533
624
|
instanceBuffer?: BufferId
|
|
625
|
+
/** One buffer per instance slot (index = the attributes' `slot`);
|
|
626
|
+
* pass this OR `instanceBuffer`, not both. */
|
|
627
|
+
instanceBuffers?: BufferId[]
|
|
534
628
|
topology?: Topology
|
|
535
629
|
depth?: boolean
|
|
536
630
|
depthWrite?: boolean
|
|
@@ -539,6 +633,7 @@ declare module "flux:gpu" {
|
|
|
539
633
|
clearColor?: [number, number, number, number]
|
|
540
634
|
render?: "auto" | "manual"
|
|
541
635
|
loadOp?: "clear" | "load"
|
|
636
|
+
samples?: 1 | 2 | 4 | 8
|
|
542
637
|
} & (DrawRange | (IndexBinding & IndexRange)) &
|
|
543
638
|
SamplerOptions &
|
|
544
639
|
LabelOption,
|
|
@@ -546,10 +641,34 @@ declare module "flux:gpu" {
|
|
|
546
641
|
|
|
547
642
|
/**
|
|
548
643
|
* Create a vertex buffer from raw bytes (interleave attribute data to match
|
|
549
|
-
* the pipeline's attribute list)
|
|
550
|
-
*
|
|
644
|
+
* the pipeline's attribute list), or from a byte length alone - a zeroed
|
|
645
|
+
* buffer, the natural create when the contents arrive through the write
|
|
646
|
+
* lease ({@link beginBufferWrite}). Buffer ids are their own space,
|
|
647
|
+
* separate from texture ids. Size is fixed for the id's lifetime: reserve
|
|
648
|
+
* the maximum up front and publish a prefix.
|
|
649
|
+
*/
|
|
650
|
+
export function createBuffer(data: Uint8Array | number, opts?: LabelOption): BufferId
|
|
651
|
+
/**
|
|
652
|
+
* Open a zero-copy write into a vertex buffer: returns an ArrayBuffer over
|
|
653
|
+
* runtime-owned memory exactly the buffer's size. Write into it in place
|
|
654
|
+
* (wrap it in a Float32Array or any view), then publish with
|
|
655
|
+
* {@link endBufferWrite} - no copy happens anywhere on the CPU path.
|
|
656
|
+
*
|
|
657
|
+
* Contents are UNSPECIFIED at begin: a recycled block holds what was
|
|
658
|
+
* published the time before last, so fill everything you publish. One open
|
|
659
|
+
* write per buffer id at a time (a second begin throws). The view is
|
|
660
|
+
* detached at end/destroy - a retained reference becomes zero-length, and
|
|
661
|
+
* writes through it are inert, never a race.
|
|
662
|
+
*/
|
|
663
|
+
export function beginBufferWrite(id: BufferId): ArrayBuffer
|
|
664
|
+
/**
|
|
665
|
+
* Publish the open write's first `byteLength` bytes at offset 0 (default:
|
|
666
|
+
* the whole buffer) and close the lease. `byteLength` 0 cancels: the lease
|
|
667
|
+
* closes and nothing is published. Always closes the lease, error or not;
|
|
668
|
+
* throws when no write is open or `byteLength` exceeds the buffer size.
|
|
669
|
+
* Pipelines drawing from the buffer re-render, like {@link writeBuffer}.
|
|
551
670
|
*/
|
|
552
|
-
export function
|
|
671
|
+
export function endBufferWrite(id: BufferId, byteLength?: number): void
|
|
553
672
|
/**
|
|
554
673
|
* Overwrite part of a vertex buffer at `byteOffset` (default 0), within the
|
|
555
674
|
* size it was created with. Pipelines drawing from the buffer re-render
|
|
@@ -575,9 +694,13 @@ declare module "flux:gpu" {
|
|
|
575
694
|
* (On a manual target nothing renders here; the range applies at its next
|
|
576
695
|
* {@link renderTarget}.) An indexed target takes the {@link IndexRange}
|
|
577
696
|
* spelling instead, bounds-checked against its index buffer; the pair
|
|
578
|
-
* that does not match the target's mode throws.
|
|
697
|
+
* that does not match the target's mode throws. Buffer keys
|
|
698
|
+
* ({@link BufferUpdate}) swap the target's buffers in the same call: the
|
|
699
|
+
* merged range is checked against the swapped buffers, so one call grows a
|
|
700
|
+
* buffer and extends the range into it, and a call that throws changes
|
|
701
|
+
* nothing (range and buffers commit together or not at all).
|
|
579
702
|
*/
|
|
580
|
-
export function setDraw(id: TextureId, draw: DrawRange | IndexRange): void
|
|
703
|
+
export function setDraw(id: TextureId, draw: (DrawRange | IndexRange) & BufferUpdate): void
|
|
581
704
|
/**
|
|
582
705
|
* Create a draw target: a render target whose contents are an ordered,
|
|
583
706
|
* mutable LIST of draws - one render clears once, then executes every
|
|
@@ -593,6 +716,10 @@ declare module "flux:gpu" {
|
|
|
593
716
|
* occlusion work. It is the storage half of the depth story; whether an
|
|
594
717
|
* entry tests/writes depth is its pipeline's `depth`/`depthWrite` state,
|
|
595
718
|
* and adding a depth-testing pipeline to a target without storage throws.
|
|
719
|
+
* `depth: "texture"` is the same storage as a SAMPLEABLE depth texture
|
|
720
|
+
* with an id of its own - {@link depthTexture} - for shadow maps,
|
|
721
|
+
* depth-of-field, SSAO; it cannot combine with `samples` (a multisampled
|
|
722
|
+
* depth texture is not sampleable; the create throws).
|
|
596
723
|
*
|
|
597
724
|
* `params` seeds the target's SHARED params - the target-level values
|
|
598
725
|
* every entry reads, the same live channel {@link setTargetParams} drives
|
|
@@ -608,8 +735,9 @@ declare module "flux:gpu" {
|
|
|
608
735
|
* "auto"` target re-renders exactly when its entries or their inputs
|
|
609
736
|
* change - a static scene costs zero passes, however many entries it
|
|
610
737
|
* holds, and one render is ONE pass however many entries it draws.
|
|
611
|
-
* `render: "manual"
|
|
612
|
-
* {@link createShaderTarget}. With no entries a render is the clear
|
|
738
|
+
* `render: "manual"`, `loadOp: "load"` and `samples` compose exactly as
|
|
739
|
+
* on {@link createShaderTarget}. With no entries a render is the clear
|
|
740
|
+
* alone.
|
|
613
741
|
* Returns a texture id (display, resize, destroy like any target; entries
|
|
614
742
|
* die with it).
|
|
615
743
|
*/
|
|
@@ -618,14 +746,34 @@ declare module "flux:gpu" {
|
|
|
618
746
|
height: number,
|
|
619
747
|
params?: ShaderParams | null,
|
|
620
748
|
opts?: {
|
|
621
|
-
depth?: boolean
|
|
622
|
-
textures?:
|
|
749
|
+
depth?: boolean | "texture"
|
|
750
|
+
textures?: TextureBindings
|
|
623
751
|
clearColor?: [number, number, number, number]
|
|
624
752
|
render?: "auto" | "manual"
|
|
625
753
|
loadOp?: "clear" | "load"
|
|
754
|
+
samples?: 1 | 2 | 4 | 8
|
|
626
755
|
} & SamplerOptions &
|
|
627
756
|
LabelOption,
|
|
628
757
|
): TextureId
|
|
758
|
+
/**
|
|
759
|
+
* The depth texture of a draw target created with `depth: "texture"`: a
|
|
760
|
+
* texture id of its own, stable for the target's life (a
|
|
761
|
+
* {@link setTargetSize} follows the color), holding the target's depth
|
|
762
|
+
* after every render - 24-bit window depth in 0..1, read as `.r` from a
|
|
763
|
+
* `sampler2D`. Bind it anywhere a texture binds ({@link setTargetTextures}
|
|
764
|
+
* for a whole scene target, an entry's `textures`, a fragment target's
|
|
765
|
+
* inputs); the dependency graph treats a binding to it as a binding to its
|
|
766
|
+
* target, so the depth pass renders first and a target sampling its own
|
|
767
|
+
* depth throws. SAMPLER-ONLY: it is not an upload texture and not a
|
|
768
|
+
* readback source (`readTexture`/`copyTexture` throw - render it through a
|
|
769
|
+
* pass to read it), its sampling is fixed at `nearest`/`clamp` (a depth
|
|
770
|
+
* texture is only complete at nearest without a comparison mode - filter
|
|
771
|
+
* in the shader, e.g. a PCF loop), and it dies with its target
|
|
772
|
+
* (`destroyTexture` on it throws). Displaying it via `<texture src>`
|
|
773
|
+
* shows the depth in the red channel. Throws for a target without texture
|
|
774
|
+
* depth.
|
|
775
|
+
*/
|
|
776
|
+
export function depthTexture(target: TextureId): TextureId
|
|
629
777
|
/**
|
|
630
778
|
* Append a draw entry to a draw target: `pipeline` draws `opts.buffer`
|
|
631
779
|
* (required when the pipeline declares attributes) with its own `params`
|
|
@@ -660,9 +808,12 @@ declare module "flux:gpu" {
|
|
|
660
808
|
pipeline: RenderPipelineId,
|
|
661
809
|
params?: ShaderParams | null,
|
|
662
810
|
opts?: {
|
|
663
|
-
textures?:
|
|
811
|
+
textures?: TextureBindings
|
|
664
812
|
buffer?: BufferId
|
|
665
813
|
instanceBuffer?: BufferId
|
|
814
|
+
/** One buffer per instance slot of the pipeline (index = the
|
|
815
|
+
* attributes' `slot`); pass this OR `instanceBuffer`, not both. */
|
|
816
|
+
instanceBuffers?: BufferId[]
|
|
666
817
|
before?: DrawId
|
|
667
818
|
} & (DrawRange | (IndexBinding & IndexRange)),
|
|
668
819
|
): DrawId
|
|
@@ -730,7 +881,7 @@ declare module "flux:gpu" {
|
|
|
730
881
|
* everywhere it is declared, and each entry's effective inputs (its own
|
|
731
882
|
* plus the applicable shared ones) must fit the device's texture units.
|
|
732
883
|
*/
|
|
733
|
-
export function setTargetTextures(target: TextureId, textures:
|
|
884
|
+
export function setTargetTextures(target: TextureId, textures: TextureBindings): void
|
|
734
885
|
/**
|
|
735
886
|
* Resize a render target of any kind in place and re-render it: the id,
|
|
736
887
|
* compiled programs, last-applied params, sampler bindings, and draw
|
|
@@ -745,13 +896,19 @@ declare module "flux:gpu" {
|
|
|
745
896
|
* validation, and cycle rules. Entries bind independently - two entries
|
|
746
897
|
* may bind the same uniform name to different sources.
|
|
747
898
|
*/
|
|
748
|
-
export function setDrawTextures(target: TextureId, draw: DrawId, textures:
|
|
899
|
+
export function setDrawTextures(target: TextureId, draw: DrawId, textures: TextureBindings): void
|
|
749
900
|
/**
|
|
750
901
|
* Update one draw entry's draw range: {@link setDraw} addressed to a
|
|
751
902
|
* single entry, same partial merge, bounds validation, and vocabulary
|
|
752
903
|
* rule (an indexed entry speaks {@link IndexRange}).
|
|
753
904
|
*/
|
|
754
905
|
export function setDrawRange(target: TextureId, draw: DrawId, update: DrawRange | IndexRange): void
|
|
906
|
+
/**
|
|
907
|
+
* Swap one draw entry's buffers: the {@link BufferUpdate} half of
|
|
908
|
+
* {@link setDraw} addressed to a single entry, same replace-only rule and
|
|
909
|
+
* range recheck.
|
|
910
|
+
*/
|
|
911
|
+
export function setDrawBuffers(target: TextureId, draw: DrawId, update: BufferUpdate): void
|
|
755
912
|
/**
|
|
756
913
|
* Reorder a draw target's list. `order` must name every current entry
|
|
757
914
|
* exactly once - a full permutation of the live {@link DrawId}s; a
|