@solidrt/flux-types 0.0.40 → 0.0.41
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/gui/camera.d.ts +14 -3
- package/gui/gpu.d.ts +333 -102
- package/index.d.ts +2 -0
- package/modules/svg.d.ts +73 -0
- package/package.json +1 -1
- package/standards/base64.d.ts +16 -0
package/gui/camera.d.ts
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
// to a bound session object, so the raw handle never leaves the runtime.
|
|
4
4
|
|
|
5
5
|
declare module "flux:camera" {
|
|
6
|
+
import type { TextureId } from "flux:gpu"
|
|
7
|
+
|
|
6
8
|
/** A camera device from {@link listCameras}. */
|
|
7
9
|
type CameraDevice = {
|
|
8
10
|
/** Device id to pass as `open({ camera })`. */
|
|
@@ -38,7 +40,7 @@ declare module "flux:camera" {
|
|
|
38
40
|
/** An opened camera session: the frame texture plus controls bound to it. */
|
|
39
41
|
type CameraSession = {
|
|
40
42
|
/** GPU texture id the latest frame is uploaded into (use as a texture source). */
|
|
41
|
-
texture:
|
|
43
|
+
texture: TextureId
|
|
42
44
|
/** Frame width in pixels. */
|
|
43
45
|
width: number
|
|
44
46
|
/** Frame height in pixels. */
|
|
@@ -52,11 +54,20 @@ declare module "flux:camera" {
|
|
|
52
54
|
close(): void
|
|
53
55
|
}
|
|
54
56
|
|
|
55
|
-
/**
|
|
57
|
+
/**
|
|
58
|
+
* List the available camera devices. The first call also starts the camera
|
|
59
|
+
* subsystem, which comes up asynchronously: expect an empty list until the
|
|
60
|
+
* initial cameraDeviceChange events arrive.
|
|
61
|
+
*/
|
|
56
62
|
export function listCameras(): CameraDevice[]
|
|
57
63
|
/**
|
|
58
64
|
* Open a camera. Opening is also the permission request: the promise rejects
|
|
59
|
-
* if permission is denied, and resolves once the first frame is ready.
|
|
65
|
+
* if permission is denied, and resolves once the first frame is ready. On
|
|
66
|
+
* Linux a session that delivers neither within 10 seconds rejects with a
|
|
67
|
+
* timeout error and releases the device (a wedged capture backend would
|
|
68
|
+
* otherwise hold it and never settle). Rejects with "camera subsystem is
|
|
69
|
+
* starting" while the subsystem is still coming up - wait for listCameras
|
|
70
|
+
* to report a device before opening.
|
|
60
71
|
*/
|
|
61
72
|
export function open(options?: CameraOpenOptions): Promise<CameraSession>
|
|
62
73
|
/**
|
package/gui/gpu.d.ts
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
// Low-level GPU textures and shaders (gui-enabled runtime only). The
|
|
2
2
|
// imperative primitive; @solidrt/core's gpu helpers add reactive auto-cleanup
|
|
3
|
-
// on top.
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
3
|
+
// on top. Each id space has its own destroyer: texture ids (the public token
|
|
4
|
+
// used as `<texture src>` and sampler inputs -> destroyTexture), buffer ids
|
|
5
|
+
// (-> destroyBuffer), and the raw shading layer's shader-stage ids
|
|
6
|
+
// (-> destroyShader), program ids (-> destroyProgram), and render-pipeline
|
|
7
|
+
// ids (-> destroyRenderPipeline).
|
|
7
8
|
// Layering: compileShader/linkProgram are the raw GL primitives (complete
|
|
8
|
-
// sources, explicit header opt-in);
|
|
9
|
-
//
|
|
9
|
+
// sources, explicit header opt-in); createRenderPipeline pairs a program with
|
|
10
|
+
// draw state (topology, blend, depth, vertex layout - how it draws);
|
|
11
|
+
// createShaderTarget builds a texture-backed target over a pipeline (size,
|
|
12
|
+
// buffer, uniforms, clear - where it draws). createShaderTexture/
|
|
13
|
+
// createPipelineTexture are fused conveniences (compile + link + pipeline +
|
|
14
|
+
// target in one call, curated preamble) - named for what they return.
|
|
10
15
|
//
|
|
11
16
|
// Sampling is a per-texture property declared at creation: every create path
|
|
12
17
|
// accepts `{ filter?, wrap? }` ("linear"/"nearest", "clamp"/"repeat";
|
|
@@ -21,15 +26,73 @@
|
|
|
21
26
|
// samples both. WITHIN one pipeline draw, `blend: "add"` accumulates
|
|
22
27
|
// overlapping geometry additively; anything else (a fragment target, or a
|
|
23
28
|
// pipeline without the option) draws with GL blending disabled and overwrites.
|
|
29
|
+
//
|
|
30
|
+
// The render contract. A target's contents are a pure function of its inputs
|
|
31
|
+
// (params, bound textures, geometry): the runtime renders it whenever inputs
|
|
32
|
+
// change - zero, one, or many times per frame, at its discretion - so a pass
|
|
33
|
+
// must not depend on its own previous output or on how often it runs. When a
|
|
34
|
+
// pass IS state (accumulation, feedback, simulation), create the target with
|
|
35
|
+
// `render: "manual"`: the runtime then never renders it, only an explicit
|
|
36
|
+
// renderTarget(id) does, in call order - the app owns the stepping. Targets
|
|
37
|
+
// sampling a manual target update after each explicit render; a manual
|
|
38
|
+
// target's own params/geometry writes take effect at its next render.
|
|
39
|
+
// `loadOp: "load"` (manual-only) keeps the previous contents under each
|
|
40
|
+
// draw - single-target accumulation - and copyTexture(src, dst) seeds or
|
|
41
|
+
// snapshots a manual target GPU-side. Both compose with renderTarget in
|
|
42
|
+
// call order.
|
|
43
|
+
//
|
|
44
|
+
// The pixel contract. Three facts hold for every texture and target:
|
|
45
|
+
//
|
|
46
|
+
// - Clip space is y-down. `gl_Position` y = -1 is the top of the target, +1
|
|
47
|
+
// the bottom (GL's row 0 is clip y = -1, and Impeller samples row 0 as the
|
|
48
|
+
// top). A vertex stage carrying camera-up geometry must negate y, or fold
|
|
49
|
+
// the flip into its projection, or it draws upside down: Vulkan's
|
|
50
|
+
// convention, not desktop GL's. The fragment path absorbs the same flip
|
|
51
|
+
// already, so `vUV` is 0..1 with top-left origin and a fragment-only shader
|
|
52
|
+
// never sees it.
|
|
53
|
+
// - Color is premultiplied alpha. A target's RGB is expected already
|
|
54
|
+
// multiplied by its A - `vec4(rgb * a, a)`, not `vec4(rgb, a)`, which
|
|
55
|
+
// composites as opaque. That is what Impeller composites and what
|
|
56
|
+
// `<texture blendMode>` blends; `clearColor` is premultiplied too, so the
|
|
57
|
+
// default transparent black needs no thought.
|
|
58
|
+
// - Values are non-linear RGBA8, with no color-space concept. Every texture
|
|
59
|
+
// and target holds 8-bit RGBA UNORM exactly as written; nothing converts to
|
|
60
|
+
// or from linear light. `filter: "linear"` averages and `blend: "add"`
|
|
61
|
+
// accumulates non-linear values - the usual approximation, stated so
|
|
62
|
+
// shaders written today stay correct if a format vocabulary arrives.
|
|
24
63
|
|
|
25
64
|
declare module "flux:gpu" {
|
|
65
|
+
/**
|
|
66
|
+
* A GPU texture handle: what every texture-producing call returns and every
|
|
67
|
+
* texture-consuming site takes (`<texture src>`, sampler bindings, the
|
|
68
|
+
* texture mutators and destroyTexture). At runtime it is a plain number;
|
|
69
|
+
* the brand exists so each id space is its own type and a cross-space slip
|
|
70
|
+
* - `destroyBuffer(textureId)`, `createShaderTarget(programId, ...)` - is a
|
|
71
|
+
* type error instead of an operation on an unrelated live resource (every
|
|
72
|
+
* space counts from 1, so a wrong id is usually a valid id in the wrong
|
|
73
|
+
* space). Ids widen to number freely; only number -> id is blocked.
|
|
74
|
+
*/
|
|
75
|
+
export type TextureId = number & { readonly __texture: unique symbol }
|
|
76
|
+
/** The vertex-buffer id space ({@link createBuffer}); see {@link TextureId} for the brand model. */
|
|
77
|
+
export type BufferId = number & { readonly __buffer: unique symbol }
|
|
78
|
+
/** The compiled-stage id space ({@link compileShader}); see {@link TextureId} for the brand model. */
|
|
79
|
+
export type ShaderStageId = number & { readonly __shaderStage: unique symbol }
|
|
80
|
+
/** The linked-program id space ({@link linkProgram}); see {@link TextureId} for the brand model. */
|
|
81
|
+
export type ProgramId = number & { readonly __program: unique symbol }
|
|
82
|
+
/** The render-pipeline id space ({@link createRenderPipeline}); see {@link TextureId} for the brand model. */
|
|
83
|
+
export type RenderPipelineId = number & { readonly __renderPipeline: unique symbol }
|
|
26
84
|
/**
|
|
27
85
|
* Shader uniform values by name. A number drives a scalar uniform (`float`,
|
|
28
86
|
* or `int`/`bool`, truncated); a flat number array drives a typed uniform
|
|
29
87
|
* whose declared GLSL type sets the expected length: 2/3/4 for
|
|
30
88
|
* `vec2`/`vec3`/`vec4`, 16 (column-major) for `mat4`. Dispatch follows the
|
|
31
|
-
* shader's own declaration
|
|
32
|
-
*
|
|
89
|
+
* shader's own declaration, and every write is validated against it at the
|
|
90
|
+
* call site: a name with no active uniform, a value whose length does not
|
|
91
|
+
* fit the declared type, a `sampler2D` named here (samplers bind via
|
|
92
|
+
* `textures`), or a value that is not a number / number array throws.
|
|
93
|
+
* Reflection only sees active uniforms, so a uniform that is declared but
|
|
94
|
+
* optimized out counts as unknown - remove the write (or use the uniform).
|
|
95
|
+
* An `undefined` value is skipped, so conditional spreads stay usable.
|
|
33
96
|
*/
|
|
34
97
|
export type ShaderParams = Record<string, number | number[]>
|
|
35
98
|
/** Magnification/minification filter; "linear" (default) or hard-pixel "nearest". */
|
|
@@ -44,22 +107,52 @@ declare module "flux:gpu" {
|
|
|
44
107
|
* matters to shaders sampling outside 0..1; the display draw never tiles.
|
|
45
108
|
*/
|
|
46
109
|
export type SamplerOptions = { filter?: FilterMode; wrap?: WrapMode }
|
|
110
|
+
/**
|
|
111
|
+
* A free-form debug name every create accepts (WebGPU's label): surfaced by
|
|
112
|
+
* the dev server's GPU inventory (get_gpu_resources) and in engine log
|
|
113
|
+
* messages, so a chain of targets reads as "bloom-h samples particle-verts"
|
|
114
|
+
* instead of anonymous ids. Not unique, never interpreted; set at create,
|
|
115
|
+
* kept across id-stable resizes ({@link resizeTexture},
|
|
116
|
+
* {@link setShaderSize}).
|
|
117
|
+
*/
|
|
118
|
+
export type LabelOption = { label?: string }
|
|
119
|
+
/**
|
|
120
|
+
* This device's hard ceilings, queried once at startup: process constants.
|
|
121
|
+
* Every create and bind validates against them at the call site, so an
|
|
122
|
+
* oversize target throws naming the limit instead of failing later as a
|
|
123
|
+
* driver error, and a binding list past the unit cap throws instead of
|
|
124
|
+
* silently sampling garbage. Values at or below these are safe on this
|
|
125
|
+
* device; the GLES 3.0 floors (2048 / 16 / 16) are the portable baseline
|
|
126
|
+
* every device guarantees.
|
|
127
|
+
*/
|
|
128
|
+
export let limits: {
|
|
129
|
+
/** Largest width/height of any texture or render target, in pixels (>= 2048). */
|
|
130
|
+
maxTextureSize: number
|
|
131
|
+
/**
|
|
132
|
+
* Sampler inputs one pass may bind (>= 16): a target's `textures`
|
|
133
|
+
* entries; on a window shader the runtime-filled `uSource` (and
|
|
134
|
+
* `uPrevious` when declared) count toward it too.
|
|
135
|
+
*/
|
|
136
|
+
maxTextureUnits: number
|
|
137
|
+
/** Vertex attributes one pipeline may declare (>= 16). */
|
|
138
|
+
maxVertexAttribs: number
|
|
139
|
+
}
|
|
47
140
|
/**
|
|
48
141
|
* Create an immutable texture from an RGBA8 pixel buffer (exactly
|
|
49
142
|
* width*height*4 bytes). Returns the texture id.
|
|
50
143
|
*/
|
|
51
|
-
export function createTexture(data: Uint8Array, width: number, height: number, opts?: SamplerOptions):
|
|
144
|
+
export function createTexture(data: Uint8Array, width: number, height: number, opts?: SamplerOptions & LabelOption): TextureId
|
|
52
145
|
/**
|
|
53
146
|
* Create a texture intended to be updated later via {@link uploadTexture}. The
|
|
54
147
|
* seed buffer must hold at least one frame (width*height*4 bytes) and may hold
|
|
55
148
|
* more (uploadTexture selects a frame by offset).
|
|
56
149
|
*/
|
|
57
|
-
export function createMutableTexture(data: Uint8Array, width: number, height: number, opts?: SamplerOptions):
|
|
150
|
+
export function createMutableTexture(data: Uint8Array, width: number, height: number, opts?: SamplerOptions & LabelOption): TextureId
|
|
58
151
|
/**
|
|
59
152
|
* Replace a mutable texture's pixels. `data` may hold several frames; `offset`
|
|
60
153
|
* (default 0) selects which frame to upload.
|
|
61
154
|
*/
|
|
62
|
-
export function uploadTexture(id:
|
|
155
|
+
export function uploadTexture(id: TextureId, data: Uint8Array, offset?: number): void
|
|
63
156
|
/**
|
|
64
157
|
* Replace a texture's storage with a new size at the same id (an id-stable
|
|
65
158
|
* resize): `<texture src>` references and shader sampler bindings keep
|
|
@@ -68,7 +161,7 @@ declare module "flux:gpu" {
|
|
|
68
161
|
* width*height*4 frame. Shader/pipeline target ids are rejected - resize
|
|
69
162
|
* those with {@link setShaderSize}.
|
|
70
163
|
*/
|
|
71
|
-
export function resizeTexture(id:
|
|
164
|
+
export function resizeTexture(id: TextureId, data: Uint8Array, width: number, height: number): void
|
|
72
165
|
/**
|
|
73
166
|
* Destroy a texture (immutable, mutable, or shader). Frame-safe: the id is
|
|
74
167
|
* reclaimed by the runtime once the render tree no longer references it, so
|
|
@@ -77,57 +170,70 @@ declare module "flux:gpu" {
|
|
|
77
170
|
* in. A destroyed id that stays mounted keeps drawing (and stays allocated)
|
|
78
171
|
* until it is unmounted or repointed.
|
|
79
172
|
*/
|
|
80
|
-
export function destroyTexture(id:
|
|
173
|
+
export function destroyTexture(id: TextureId): void
|
|
81
174
|
/**
|
|
82
175
|
* Compile a GLSL ES fragment shader into an offscreen texture of the given
|
|
83
|
-
* size. `params` sets uniforms by name (see {@link ShaderParams}
|
|
84
|
-
* value shapes
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
176
|
+
* size. `params` sets initial uniforms by name (see {@link ShaderParams}
|
|
177
|
+
* for the value shapes and the validation contract - a typo'd name throws
|
|
178
|
+
* here, at the create). It is its own argument, not an option, because it
|
|
179
|
+
* is the initial value of a live channel - the same values the `<texture
|
|
180
|
+
* params>` prop and {@link setShaderParams} drive later; pass `null` (or
|
|
181
|
+
* omit it) for a shader with none. `opts.textures` binds sampler2D
|
|
182
|
+
* uniforms to texture ids - any texture id, including another
|
|
183
|
+
* shader/pipeline target's output, under a name that must be an active
|
|
184
|
+
* `sampler2D` uniform. Bound targets are live dependencies: when a source
|
|
185
|
+
* re-renders (its params, geometry, or data change), every target sampling
|
|
186
|
+
* it re-renders too, transitively through chains, before the next frame or
|
|
187
|
+
* readback - no per-frame uniform write is needed to keep a chain current.
|
|
188
|
+
* Returns the resulting texture id. The fused convenience: one call
|
|
189
|
+
* compiles a program and creates a target over it, and the program lives
|
|
190
|
+
* and dies with the target. To share one compile across targets (or hold a
|
|
191
|
+
* program with no target yet), use the raw layer: {@link compileShader} +
|
|
192
|
+
* {@link linkProgram} + {@link createRenderPipeline} +
|
|
193
|
+
* {@link createShaderTarget}.
|
|
94
194
|
*
|
|
95
|
-
* The preamble (`#version 300 es`, precision, `vUV`, `iResolution`,
|
|
195
|
+
* The preamble (`#version 300 es`, precision, `vUV`, `iResolution`,
|
|
96
196
|
* `fragColor`) is injected only into sources that do not declare their own
|
|
97
|
-
* `#version` line
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
|
|
105
|
-
|
|
197
|
+
* `#version` line, and declares exactly what the runtime provides - an
|
|
198
|
+
* app-driven uniform (a time value, say) is the source's own declaration,
|
|
199
|
+
* driven through params like any other. A source that starts with
|
|
200
|
+
* `#version 300 es` is compiled exactly as written, so a shader with its
|
|
201
|
+
* own uniform names (a port from elsewhere) needs no rewriting and no drop
|
|
202
|
+
* to the raw layer. The built-in vertex stage still supplies `vUV` to a
|
|
203
|
+
* complete source; declare `in vec2 vUV;` yourself to read it. Same rule on
|
|
204
|
+
* {@link createPipelineTexture}. A complete source may also declare
|
|
205
|
+
* `iResolution` as vec3 (the Shadertoy shape); it is then filled as
|
|
206
|
+
* `(w, h, 1.0)`.
|
|
207
|
+
*/
|
|
208
|
+
export function createShaderTexture(
|
|
106
209
|
fragmentSrc: string,
|
|
107
210
|
width: number,
|
|
108
211
|
height: number,
|
|
109
|
-
params?: ShaderParams,
|
|
110
|
-
textures?: Record<string,
|
|
111
|
-
|
|
112
|
-
): number
|
|
212
|
+
params?: ShaderParams | null,
|
|
213
|
+
opts?: { textures?: Record<string, TextureId> } & SamplerOptions & LabelOption,
|
|
214
|
+
): TextureId
|
|
113
215
|
/**
|
|
114
216
|
* Compile a single shader stage from raw GLSL ES: the primitive under
|
|
115
217
|
* {@link linkProgram}, GL's own model (a "shader" is one stage; linking
|
|
116
218
|
* stages yields a program). The source is complete - it declares its own
|
|
117
219
|
* `#version 300 es`, precision, varyings and uniforms; nothing is injected.
|
|
118
220
|
* With `header: true` the standard header is prepended explicitly: `#version
|
|
119
|
-
* 300 es`, `precision highp float;`, `uniform vec2 iResolution;`,
|
|
120
|
-
*
|
|
121
|
-
*
|
|
221
|
+
* 300 es`, `precision highp float;`, `uniform vec2 iResolution;`, plus
|
|
222
|
+
* `out vec4 fragColor;` for a fragment stage (the same text
|
|
223
|
+
* {@link createPipelineTexture} injects). Do not combine `header` with your
|
|
122
224
|
* own `#version` line. Returns a shader (stage) id in its own id space;
|
|
123
225
|
* compile errors throw here, synchronously, at a call site the app chose.
|
|
124
226
|
* Free with {@link destroyShader}.
|
|
227
|
+
*
|
|
228
|
+
* A vertex stage writes into a y-down clip space: `gl_Position` y = -1 is
|
|
229
|
+
* the top row of the target and +1 the bottom, so camera-up geometry must
|
|
230
|
+
* negate y (or fold the flip into its projection) to display up.
|
|
125
231
|
*/
|
|
126
232
|
export function compileShader(
|
|
127
233
|
stage: "vertex" | "fragment",
|
|
128
234
|
source: string,
|
|
129
235
|
opts?: { header?: boolean },
|
|
130
|
-
):
|
|
236
|
+
): ShaderStageId
|
|
131
237
|
/**
|
|
132
238
|
* Link a compiled vertex and fragment stage into a program, returning a
|
|
133
239
|
* program id (its own id space, like buffers - not a texture id). Link
|
|
@@ -137,70 +243,127 @@ declare module "flux:gpu" {
|
|
|
137
243
|
* Creating targets from the returned handle compiles nothing. Free with
|
|
138
244
|
* {@link destroyProgram}.
|
|
139
245
|
*/
|
|
140
|
-
export function linkProgram(vertexShader:
|
|
246
|
+
export function linkProgram(vertexShader: ShaderStageId, fragmentShader: ShaderStageId, opts?: LabelOption): ProgramId
|
|
141
247
|
/**
|
|
142
248
|
* Destroy a compiled stage by id. Programs linked from it are unaffected.
|
|
143
249
|
*/
|
|
144
|
-
export function destroyShader(id:
|
|
250
|
+
export function destroyShader(id: ShaderStageId): void
|
|
145
251
|
/**
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
252
|
+
* Pair a linked program with draw state, returning a render pipeline id
|
|
253
|
+
* (its own id space, like programs and buffers - not a texture id): the
|
|
254
|
+
* pipeline state object of every modern GPU API. The pipeline owns HOW its
|
|
255
|
+
* targets draw - `attributes` (the interleaved vertex layout; omit for
|
|
256
|
+
* attributeless rendering via gl_VertexID), `topology`, `blend`, `depth`,
|
|
257
|
+
* `depthWrite` (`false` requires `depth: true`) - while each target brings
|
|
258
|
+
* its own size, buffer, uniforms, and clear. Creating a pipeline compiles
|
|
259
|
+
* nothing, and many pipelines may share one program. The vocabulary is
|
|
260
|
+
* validated here, so a bad word throws at this call site. Free with
|
|
261
|
+
* {@link destroyRenderPipeline}; the program is yours and outlives it.
|
|
156
262
|
*/
|
|
157
|
-
export function
|
|
158
|
-
program:
|
|
159
|
-
width: number,
|
|
160
|
-
height: number,
|
|
263
|
+
export function createRenderPipeline(
|
|
264
|
+
program: ProgramId,
|
|
161
265
|
opts?: {
|
|
162
|
-
params?: ShaderParams
|
|
163
|
-
textures?: Record<string, number>
|
|
164
266
|
attributes?: VertexAttribute[]
|
|
165
|
-
buffer?: number
|
|
166
267
|
topology?: Topology
|
|
167
|
-
|
|
268
|
+
blend?: BlendMode
|
|
168
269
|
depth?: boolean
|
|
169
270
|
depthWrite?: boolean
|
|
170
|
-
|
|
271
|
+
} & LabelOption,
|
|
272
|
+
): RenderPipelineId
|
|
273
|
+
/**
|
|
274
|
+
* Destroy a render pipeline by id. Targets created from it are unaffected:
|
|
275
|
+
* each holds the pipeline until it is itself destroyed, so either
|
|
276
|
+
* destruction order is safe. The id stops being usable for new targets
|
|
277
|
+
* immediately.
|
|
278
|
+
*/
|
|
279
|
+
export function destroyRenderPipeline(id: RenderPipelineId): void
|
|
280
|
+
/**
|
|
281
|
+
* Create a render target over a {@link createRenderPipeline} pipeline and
|
|
282
|
+
* render it once: the target half of {@link createPipelineTexture}. Returns
|
|
283
|
+
* a texture id exactly like the fused creates do (drive uniforms
|
|
284
|
+
* via the `params` prop or {@link setShaderParams}, resize with
|
|
285
|
+
* {@link setShaderSize}, destroy with {@link destroyTexture}). Many targets
|
|
286
|
+
* may share one pipeline, and creating a target compiles nothing. `buffer`
|
|
287
|
+
* supplies the concrete vertex buffer the pipeline's attribute layout
|
|
288
|
+
* describes (required when the pipeline declares attributes); the
|
|
289
|
+
* {@link DrawRange} keys pick what is drawn from it - `vertexCount`
|
|
290
|
+
* defaults to the rest of the buffer from `firstVertex` on,
|
|
291
|
+
* `instanceCount` repeats the range - and a vertex fetch past the
|
|
292
|
+
* buffer's end throws here. A fullscreen pass over an attributeless
|
|
293
|
+
* pipeline is `vertexCount: 3` with a covering-triangle vertex stage.
|
|
294
|
+
* Draw-state keys
|
|
295
|
+
* (`attributes`, `topology`, `blend`, `depth`, `depthWrite`) belong to the
|
|
296
|
+
* pipeline and throw here. `params` and `textures` are validated against
|
|
297
|
+
* the pipeline's program (see {@link ShaderParams}).
|
|
298
|
+
*
|
|
299
|
+
* `render: "manual"` opts the target out of runtime-driven rendering (see
|
|
300
|
+
* the render contract above): it starts cleared to `clearColor` and its
|
|
301
|
+
* pass runs only when {@link renderTarget} is called.
|
|
302
|
+
*
|
|
303
|
+
* `loadOp` chooses what each render finds in the target: `"clear"` (the
|
|
304
|
+
* default) clears to `clearColor` first, `"load"` keeps the previous
|
|
305
|
+
* contents and draws over them - single-target accumulation (with the
|
|
306
|
+
* pipeline's `blend: "add"`, an additive trail; without blending, draws
|
|
307
|
+
* simply land over old pixels). `"load"` requires `render: "manual"` and
|
|
308
|
+
* throws otherwise: on a runtime-rendered target the output would depend
|
|
309
|
+
* on how often the runtime happened to render. Depth (when the pipeline
|
|
310
|
+
* has it) is per-render scratch and always clears; creation, resize, and
|
|
311
|
+
* nothing else reset the color to `clearColor`. State that needs a
|
|
312
|
+
* read-modify-write of its own pixels (decay, blur, simulation) still
|
|
313
|
+
* ping-pongs across two manual targets - a pass can never sample the
|
|
314
|
+
* texture it writes.
|
|
315
|
+
*/
|
|
316
|
+
export function createShaderTarget(
|
|
317
|
+
pipeline: RenderPipelineId,
|
|
318
|
+
width: number,
|
|
319
|
+
height: number,
|
|
320
|
+
params?: ShaderParams | null,
|
|
321
|
+
opts?: {
|
|
322
|
+
textures?: Record<string, TextureId>
|
|
323
|
+
buffer?: BufferId
|
|
171
324
|
clearColor?: [number, number, number, number]
|
|
172
|
-
|
|
173
|
-
|
|
325
|
+
render?: "auto" | "manual"
|
|
326
|
+
loadOp?: "clear" | "load"
|
|
327
|
+
} & DrawRange &
|
|
328
|
+
SamplerOptions &
|
|
329
|
+
LabelOption,
|
|
330
|
+
): TextureId
|
|
174
331
|
/**
|
|
175
|
-
* Destroy a linked program by id.
|
|
332
|
+
* Destroy a linked program by id. Pipelines created from it are unaffected:
|
|
176
333
|
* each holds the program until it is itself destroyed, so either
|
|
177
|
-
* destruction order is safe. The id stops being usable for new
|
|
334
|
+
* destruction order is safe. The id stops being usable for new pipelines
|
|
178
335
|
* immediately.
|
|
179
336
|
*/
|
|
180
|
-
export function destroyProgram(id:
|
|
337
|
+
export function destroyProgram(id: ProgramId): void
|
|
181
338
|
/**
|
|
182
339
|
* Update a shader texture's uniforms by name and re-render it (see
|
|
183
|
-
* {@link ShaderParams} for the value shapes
|
|
340
|
+
* {@link ShaderParams} for the value shapes and the validation contract -
|
|
341
|
+
* an unknown name or a mismatched length throws here, on the line that
|
|
342
|
+
* wrote it). On a manual target nothing renders here; the values apply at
|
|
343
|
+
* its next {@link renderTarget}.
|
|
184
344
|
*/
|
|
185
|
-
export function setShaderParams(id:
|
|
345
|
+
export function setShaderParams(id: TextureId, params: ShaderParams): void
|
|
186
346
|
/**
|
|
187
347
|
* Rebind a shader texture's sampler2D inputs by uniform name and re-render
|
|
188
348
|
* it with its last-applied params - the sampler analog of
|
|
189
349
|
* {@link setShaderParams}. Bindings not named keep their current source, so
|
|
190
350
|
* a single input can be retargeted (post-process source swap, ping-pong
|
|
191
351
|
* between two data textures) without recompiling the shader. Throws if the
|
|
192
|
-
* shader or a source texture id is unknown,
|
|
193
|
-
*
|
|
194
|
-
*
|
|
352
|
+
* shader or a source texture id is unknown, if a binding names anything
|
|
353
|
+
* but an active `sampler2D` uniform, if it names the shader's own target
|
|
354
|
+
* (same-pass feedback), or if it would close a sampling cycle among
|
|
355
|
+
* runtime-rendered targets. A cycle through a
|
|
356
|
+
* `render: "manual"` target is legal - the runtime never renders one, so
|
|
357
|
+
* the loop only steps when the app calls {@link renderTarget}.
|
|
195
358
|
*/
|
|
196
|
-
export function setShaderTextures(id:
|
|
359
|
+
export function setShaderTextures(id: TextureId, textures: Record<string, TextureId>): void
|
|
197
360
|
/**
|
|
198
361
|
* Resize a shader or pipeline target texture in place and re-render it: the
|
|
199
362
|
* id, compiled program, last-applied params, and sampler bindings all carry
|
|
200
|
-
* over; only the output size changes. The
|
|
363
|
+
* over; only the output size changes. The setDraw analog for output
|
|
201
364
|
* size.
|
|
202
365
|
*/
|
|
203
|
-
export function setShaderSize(id:
|
|
366
|
+
export function setShaderSize(id: TextureId, width: number, height: number): void
|
|
204
367
|
|
|
205
368
|
export type Topology = "points" | "lines" | "line-strip" | "triangles" | "triangle-strip"
|
|
206
369
|
/**
|
|
@@ -220,64 +383,131 @@ declare module "flux:gpu" {
|
|
|
220
383
|
* vertex shader's `in` declarations.
|
|
221
384
|
*/
|
|
222
385
|
export type VertexAttribute = { name: string; format: "f32" | "vec2" | "vec3" | "vec4" }
|
|
386
|
+
/**
|
|
387
|
+
* A pipeline target's draw as data, WebGPU-style: `firstVertex` +
|
|
388
|
+
* `vertexCount` pick the vertex range `[firstVertex, firstVertex +
|
|
389
|
+
* vertexCount)` of the buffer, `instanceCount` draws that range as N
|
|
390
|
+
* instances (`glDrawArraysInstanced`) told apart by `gl_InstanceID`. All
|
|
391
|
+
* keys optional: at create, `firstVertex` defaults to 0, `vertexCount` to
|
|
392
|
+
* the rest of the buffer and `instanceCount` to 1 (the plain draw); in
|
|
393
|
+
* {@link setDraw}, absent keys keep their current value. `instanceCount: 0`
|
|
394
|
+
* draws nothing - a cheap off switch. Two GL facts worth knowing:
|
|
395
|
+
* `gl_VertexID` includes `firstVertex` (as in WebGPU), and `gl_InstanceID`
|
|
396
|
+
* always counts from 0 - ES 3.0 has no base instance.
|
|
397
|
+
*/
|
|
398
|
+
export type DrawRange = { firstVertex?: number; vertexCount?: number; instanceCount?: number }
|
|
223
399
|
|
|
224
400
|
/**
|
|
225
401
|
* Compile a GLSL ES vertex+fragment pipeline into an offscreen texture of
|
|
226
402
|
* the given size and render it once. Sources without a `#version` line get
|
|
227
|
-
* a 300 es preamble declaring `iResolution
|
|
228
|
-
*
|
|
229
|
-
* `
|
|
230
|
-
*
|
|
231
|
-
* (
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
403
|
+
* a 300 es preamble declaring `iResolution` (no vUV: varyings are the
|
|
404
|
+
* pipeline's own; app-driven uniforms are the source's own declarations).
|
|
405
|
+
* Clip space is y-down: `gl_Position` y = -1 is the top
|
|
406
|
+
* row of the target and +1 the bottom, so camera-up geometry must negate y
|
|
407
|
+
* (or fold the flip into its projection) to display up. `attributes`
|
|
408
|
+
* describes one interleaved vertex in `buffer` (a {@link createBuffer} id);
|
|
409
|
+
* omit both for attributeless rendering via gl_VertexID. The
|
|
410
|
+
* {@link DrawRange} keys pick what is drawn: `vertexCount` defaults to the
|
|
411
|
+
* rest of the buffer from `firstVertex` on, `instanceCount` draws the
|
|
412
|
+
* range as N instances told apart by `gl_InstanceID`; a vertex fetch past
|
|
413
|
+
* the buffer's end throws. With
|
|
414
|
+
* `depth: true` the pipeline gets a private depth buffer, cleared and tested
|
|
415
|
+
* on every render; `depthWrite: false` (requires `depth: true`) keeps the
|
|
416
|
+
* test but stops the draw from writing depth. `blend` sets the draw's own blending (see
|
|
235
417
|
* {@link BlendMode}); an additive pass over a depth buffer is
|
|
236
418
|
* `{ depth: true, blend: "add", depthWrite: false }`, stated explicitly.
|
|
237
419
|
* The target is cleared to `clearColor` (default transparent black) before
|
|
238
|
-
* each draw.
|
|
420
|
+
* each draw. `render: "manual"` and `loadOp` behave exactly as on
|
|
421
|
+
* {@link createShaderTarget}: no runtime-driven renders, step with
|
|
422
|
+
* {@link renderTarget}, and `loadOp: "load"` (manual-only) keeps the
|
|
423
|
+
* previous contents under each draw.
|
|
239
424
|
* Returns a texture id: display it with `<texture src>`, drive uniforms via
|
|
240
425
|
* the `params` prop or {@link setShaderParams}, destroy with
|
|
241
426
|
* {@link destroyTexture}.
|
|
242
427
|
*/
|
|
243
|
-
export function
|
|
428
|
+
export function createPipelineTexture(
|
|
244
429
|
vertexSrc: string,
|
|
245
430
|
fragmentSrc: string,
|
|
246
431
|
width: number,
|
|
247
432
|
height: number,
|
|
433
|
+
params?: ShaderParams | null,
|
|
248
434
|
opts?: {
|
|
249
|
-
|
|
250
|
-
textures?: Record<string, number>
|
|
435
|
+
textures?: Record<string, TextureId>
|
|
251
436
|
attributes?: VertexAttribute[]
|
|
252
|
-
buffer?:
|
|
437
|
+
buffer?: BufferId
|
|
253
438
|
topology?: Topology
|
|
254
|
-
vertexCount?: number
|
|
255
439
|
depth?: boolean
|
|
256
440
|
depthWrite?: boolean
|
|
257
441
|
blend?: BlendMode
|
|
258
442
|
clearColor?: [number, number, number, number]
|
|
259
|
-
|
|
260
|
-
|
|
443
|
+
render?: "auto" | "manual"
|
|
444
|
+
loadOp?: "clear" | "load"
|
|
445
|
+
} & DrawRange &
|
|
446
|
+
SamplerOptions &
|
|
447
|
+
LabelOption,
|
|
448
|
+
): TextureId
|
|
261
449
|
|
|
262
450
|
/**
|
|
263
451
|
* Create a vertex buffer from raw bytes (interleave attribute data to match
|
|
264
452
|
* the pipeline's attribute list). Buffer ids are their own space, separate
|
|
265
453
|
* from texture ids.
|
|
266
454
|
*/
|
|
267
|
-
export function createBuffer(data: Uint8Array):
|
|
455
|
+
export function createBuffer(data: Uint8Array, opts?: LabelOption): BufferId
|
|
268
456
|
/**
|
|
269
457
|
* Overwrite part of a vertex buffer at `byteOffset` (default 0), within the
|
|
270
458
|
* size it was created with. Pipelines drawing from the buffer re-render
|
|
271
459
|
* with their last-applied params.
|
|
272
460
|
*/
|
|
273
|
-
export function writeBuffer(id:
|
|
274
|
-
/**
|
|
275
|
-
|
|
461
|
+
export function writeBuffer(id: BufferId, data: Uint8Array, byteOffset?: number): void
|
|
462
|
+
/**
|
|
463
|
+
* Destroy a vertex buffer. Pipeline textures drawing from it hold their own
|
|
464
|
+
* reference, so destruction order does not matter; further writes to the id
|
|
465
|
+
* throw.
|
|
466
|
+
*/
|
|
467
|
+
export function destroyBuffer(id: BufferId): void
|
|
468
|
+
/**
|
|
469
|
+
* Update a pipeline texture's draw range and re-render it: `vertexCount`
|
|
470
|
+
* after writing a variable amount of dynamic geometry into its buffer,
|
|
471
|
+
* `firstVertex` to draw a different window of a shared buffer,
|
|
472
|
+
* `instanceCount` to grow or shrink an instanced population. Keys absent
|
|
473
|
+
* from `draw` keep their current value, like params. Throws if a value is
|
|
474
|
+
* negative or the merged range's vertex fetch would run past the end of
|
|
475
|
+
* the target's buffer ((firstVertex + vertexCount) x vertex stride >
|
|
476
|
+
* buffer size) - the out-of-bounds draw GL itself never checks; a target
|
|
477
|
+
* without vertex fetch (attributeless) accepts any non-negative range.
|
|
478
|
+
* (On a manual target nothing renders here; the range applies at its next
|
|
479
|
+
* {@link renderTarget}.)
|
|
480
|
+
*/
|
|
481
|
+
export function setDraw(id: TextureId, draw: DrawRange): void
|
|
482
|
+
/**
|
|
483
|
+
* Render a `render: "manual"` target once, now. Renders land in call order
|
|
484
|
+
* relative to every other GPU call: a `setShaderParams`/`writeBuffer`
|
|
485
|
+
* issued before is visible to the pass, a {@link readTexture} issued after
|
|
486
|
+
* observes it, and two renders run the pass twice in order. Inputs are
|
|
487
|
+
* fresh: pending runtime-driven renders of sampled targets resolve first.
|
|
488
|
+
* Targets sampling this one update after the render. Throws if the id is
|
|
489
|
+
* not a manual target - the runtime owns rendering the others, and a pass
|
|
490
|
+
* that depends on how often it runs is only well-defined when the app is
|
|
491
|
+
* the one counting. Ping-pong feedback is two manual targets sampling
|
|
492
|
+
* each other, stepped alternately from `onFrame`; binding a target to
|
|
493
|
+
* ITSELF still throws (same-pass GL feedback, undefined pixels regardless
|
|
494
|
+
* of who schedules it).
|
|
495
|
+
*/
|
|
496
|
+
export function renderTarget(id: TextureId): void
|
|
276
497
|
/**
|
|
277
|
-
*
|
|
278
|
-
*
|
|
498
|
+
* Overwrite a `render: "manual"` target with another texture's current
|
|
499
|
+
* pixels, GPU-side: the seed/history analog of {@link uploadTexture}
|
|
500
|
+
* (seed a `loadOp: "load"` accumulator, snapshot one ping-pong buffer
|
|
501
|
+
* into another, reset state to a known image). Exact and same-size only -
|
|
502
|
+
* content and row order are preserved, and a size mismatch throws (a
|
|
503
|
+
* scaling copy is an ordinary pass). Copies land in call order like
|
|
504
|
+
* renders: a copy after a render sees that render, a readback after a
|
|
505
|
+
* copy sees the copy, and targets sampling `dst` update afterwards.
|
|
506
|
+
* Throws if either id is unknown, `dst` is not a manual target (the
|
|
507
|
+
* runtime owns those contents), or `src === dst`. `src` may be any
|
|
508
|
+
* texture: uploaded, mutable, a camera frame, or another target's output.
|
|
279
509
|
*/
|
|
280
|
-
export function
|
|
510
|
+
export function copyTexture(src: TextureId, dst: TextureId): void
|
|
281
511
|
/**
|
|
282
512
|
* Capture a render-tree node's subtree into a new GPU texture, resolving once
|
|
283
513
|
* it has been rendered on the next paint pass. The node must be attached to
|
|
@@ -310,11 +540,12 @@ declare module "flux:gpu" {
|
|
|
310
540
|
* must stay current has to come from a source that updates in place: another
|
|
311
541
|
* pipeline's render target, a camera texture, a mutable texture.
|
|
312
542
|
*/
|
|
313
|
-
export function captureSnapshot(nodeId: number): Promise<{ id:
|
|
543
|
+
export function captureSnapshot(nodeId: number): Promise<{ id: TextureId; width: number; height: number }>
|
|
314
544
|
/**
|
|
315
545
|
* Read back a registered texture's current pixels as RGBA8 (tightly packed,
|
|
316
546
|
* top-to-bottom rows), for any texture id whatever created it (createTexture,
|
|
317
|
-
*
|
|
547
|
+
* createShaderTexture, captureSnapshot). Synchronous. Throws if the id is
|
|
548
|
+
* unknown.
|
|
318
549
|
*/
|
|
319
|
-
export function readTexture(id:
|
|
550
|
+
export function readTexture(id: TextureId): { width: number; height: number; data: Uint8Array }
|
|
320
551
|
}
|
package/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
/// <reference path="./modules/fs.d.ts" />
|
|
5
5
|
/// <reference path="./modules/sqlite.d.ts" />
|
|
6
6
|
/// <reference path="./modules/subprocess.d.ts" />
|
|
7
|
+
/// <reference path="./modules/svg.d.ts" />
|
|
7
8
|
/// <reference path="./modules/p2p.d.ts" />
|
|
8
9
|
/// <reference path="./modules/net.d.ts" />
|
|
9
10
|
/// <reference path="./modules/mdns.d.ts" />
|
|
@@ -16,6 +17,7 @@
|
|
|
16
17
|
/// <reference path="./standards/console.d.ts" />
|
|
17
18
|
/// <reference path="./standards/time.d.ts" />
|
|
18
19
|
/// <reference path="./standards/text.d.ts" />
|
|
20
|
+
/// <reference path="./standards/base64.d.ts" />
|
|
19
21
|
/// <reference path="./standards/fetch.d.ts" />
|
|
20
22
|
/// <reference path="./standards/websocket.d.ts" />
|
|
21
23
|
|
package/modules/svg.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
declare module "flux:svg" {
|
|
2
|
+
/**
|
|
3
|
+
* A gradient paint from a parsed document, in the branded shape the render
|
|
4
|
+
* tree decodes: coordinates are absolute document-space values
|
|
5
|
+
* (`units: "absolute"`), `spread` is the SVG spreadMethod (absent = pad),
|
|
6
|
+
* and `transform` an SVG matrix(a b c d e f) sextet mapping the gradient's
|
|
7
|
+
* coordinates into the document space (absent = identity). Stop colors are
|
|
8
|
+
* packed `0xRRGGBBAA` numbers.
|
|
9
|
+
*/
|
|
10
|
+
export type SvgGradient =
|
|
11
|
+
| {
|
|
12
|
+
__gradient: "linear"
|
|
13
|
+
units: "absolute"
|
|
14
|
+
x0: number
|
|
15
|
+
y0: number
|
|
16
|
+
x1: number
|
|
17
|
+
y1: number
|
|
18
|
+
stops: { offset: number; color: number }[]
|
|
19
|
+
spread?: "reflect" | "repeat"
|
|
20
|
+
transform?: [number, number, number, number, number, number]
|
|
21
|
+
}
|
|
22
|
+
| {
|
|
23
|
+
__gradient: "radial"
|
|
24
|
+
units: "absolute"
|
|
25
|
+
cx: number
|
|
26
|
+
cy: number
|
|
27
|
+
r: number
|
|
28
|
+
stops: { offset: number; color: number }[]
|
|
29
|
+
spread?: "reflect" | "repeat"
|
|
30
|
+
transform?: [number, number, number, number, number, number]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* One resolved draw in document coordinates. The keys deliberately match
|
|
35
|
+
* the path element's props, so a draw spreads onto a `<d-path>` unchanged.
|
|
36
|
+
* A source path with both a fill and a stroke yields two draws (fill
|
|
37
|
+
* first). Solid colors are `#rrggbbaa` strings; stroke keys are only
|
|
38
|
+
* present on stroke draws, `fillRule` only on fills.
|
|
39
|
+
*/
|
|
40
|
+
export type SvgDraw = {
|
|
41
|
+
d: string
|
|
42
|
+
color: string | SvgGradient
|
|
43
|
+
drawStyle: "fill" | "stroke"
|
|
44
|
+
fillRule?: "nonzero" | "evenodd"
|
|
45
|
+
strokeWidth?: number
|
|
46
|
+
strokeCap?: "butt" | "round" | "square"
|
|
47
|
+
strokeJoin?: "miter" | "round" | "bevel"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** A parsed document: intrinsic size (viewBox/width-height) plus the flat draw list. */
|
|
51
|
+
export type SvgDocument = {
|
|
52
|
+
width: number
|
|
53
|
+
height: number
|
|
54
|
+
draws: SvgDraw[]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Parses an SVG document string into plain draw data: geometry is flattened
|
|
59
|
+
* to absolute path data (every group/element transform baked in) and paints
|
|
60
|
+
* are resolved to solid colors or gradients. Parsing is sandboxed: no
|
|
61
|
+
* network, file, or data-URI resource access. Throws on an invalid
|
|
62
|
+
* document.
|
|
63
|
+
*
|
|
64
|
+
* `opts.color` drives `currentColor` in the document, as a packed
|
|
65
|
+
* `0xRRGGBBAA` number (alpha ignored); explicit fills/strokes still win.
|
|
66
|
+
* The `@solidrt/core` re-export `parseSvg` accepts any CSS color string
|
|
67
|
+
* instead and is the surface applications normally use.
|
|
68
|
+
*
|
|
69
|
+
* Unsupported (skipped): clipPath, masks, filters, patterns, embedded
|
|
70
|
+
* images, and SVG text.
|
|
71
|
+
*/
|
|
72
|
+
export function parseSvg(src: string, opts?: { color?: number }): SvgDocument
|
|
73
|
+
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// atob / btoa. Base64 over "binary strings" (WHATWG): the string is a byte
|
|
2
|
+
// container, not text - each char code is one raw byte in 0..=255, with no
|
|
3
|
+
// UTF-8 step in either direction.
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Base64-encode a binary string: each char code is taken as one raw byte.
|
|
7
|
+
* Throws if the string contains a code point above 255 (encode real text by
|
|
8
|
+
* taking its bytes first, e.g. via {@link TextEncoder}).
|
|
9
|
+
*/
|
|
10
|
+
declare function btoa(data: string): string
|
|
11
|
+
/**
|
|
12
|
+
* Base64-decode to a binary string: each decoded byte becomes one char code
|
|
13
|
+
* (read the bytes back with `charCodeAt`). ASCII whitespace in the input is
|
|
14
|
+
* ignored; anything else that is not valid base64 throws.
|
|
15
|
+
*/
|
|
16
|
+
declare function atob(data: string): string
|