@solidrt/flux-types 0.0.38 → 0.0.40

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.
Files changed (2) hide show
  1. package/gui/gpu.d.ts +190 -18
  2. package/package.json +1 -1
package/gui/gpu.d.ts CHANGED
@@ -1,20 +1,60 @@
1
- // Low-level GPU textures and fragment shaders (gui-enabled runtime only). The
2
- // imperative primitive; @solidrt/core's gpu helpers add reactive auto-cleanup on
3
- // top. Texture ids are the public token (used as `<texture src>` and shader
4
- // sampler inputs), so there is no handle to hide here.
1
+ // Low-level GPU textures and shaders (gui-enabled runtime only). The
2
+ // imperative primitive; @solidrt/core's gpu helpers add reactive auto-cleanup
3
+ // on top. Three id spaces, each destroyed by its own destroyer: texture ids
4
+ // (the public token used as `<texture src>` and sampler inputs ->
5
+ // destroyTexture), buffer ids (-> destroyBuffer), and the raw shading layer's
6
+ // shader-stage ids (-> destroyShader) and program ids (-> destroyProgram).
7
+ // Layering: compileShader/linkProgram are the raw GL primitives (complete
8
+ // sources, explicit header opt-in); createShader/createPipeline are fused
9
+ // conveniences (compile + link + target in one call, curated preamble).
10
+ //
11
+ // Sampling is a per-texture property declared at creation: every create path
12
+ // accepts `{ filter?, wrap? }` ("linear"/"nearest", "clamp"/"repeat";
13
+ // defaults linear + clamp for every origin). The state follows the id
14
+ // everywhere it is sampled - shader passes and `<texture>` display alike -
15
+ // and survives id-stable resizes. It cannot be changed after creation. No
16
+ // mipmaps exist.
17
+ //
18
+ // Compositing several targets is a render-tree job, not a shader one: stack
19
+ // `<texture>` elements and set their `blendMode` (the full Skia set, e.g.
20
+ // "plus" for an additive pass over a base pass) instead of writing a pass that
21
+ // samples both. WITHIN one pipeline draw, `blend: "add"` accumulates
22
+ // overlapping geometry additively; anything else (a fragment target, or a
23
+ // pipeline without the option) draws with GL blending disabled and overwrites.
5
24
 
6
25
  declare module "flux:gpu" {
26
+ /**
27
+ * Shader uniform values by name. A number drives a scalar uniform (`float`,
28
+ * or `int`/`bool`, truncated); a flat number array drives a typed uniform
29
+ * whose declared GLSL type sets the expected length: 2/3/4 for
30
+ * `vec2`/`vec3`/`vec4`, 16 (column-major) for `mat4`. Dispatch follows the
31
+ * shader's own declaration; a value whose length does not fit it is skipped
32
+ * with a runtime warning, as is a name with no active uniform.
33
+ */
34
+ export type ShaderParams = Record<string, number | number[]>
35
+ /** Magnification/minification filter; "linear" (default) or hard-pixel "nearest". */
36
+ export type FilterMode = "linear" | "nearest"
37
+ /** Sampling outside 0..1: "clamp" (default, extend edge pixels) or "repeat" (tile). */
38
+ export type WrapMode = "clamp" | "repeat"
39
+ /**
40
+ * Per-texture sampling, declared at creation and fixed for the id's
41
+ * lifetime. Applies wherever the texture is sampled: shader/pipeline
42
+ * sampler2D inputs AND `<texture src>` display (a "nearest" texture
43
+ * upscales with hard pixels on screen - the pixel-art path). `wrap` only
44
+ * matters to shaders sampling outside 0..1; the display draw never tiles.
45
+ */
46
+ export type SamplerOptions = { filter?: FilterMode; wrap?: WrapMode }
7
47
  /**
8
48
  * Create an immutable texture from an RGBA8 pixel buffer (exactly
9
49
  * width*height*4 bytes). Returns the texture id.
10
50
  */
11
- export function createTexture(data: Uint8Array, width: number, height: number): number
51
+ export function createTexture(data: Uint8Array, width: number, height: number, opts?: SamplerOptions): number
12
52
  /**
13
53
  * Create a texture intended to be updated later via {@link uploadTexture}. The
14
54
  * seed buffer must hold at least one frame (width*height*4 bytes) and may hold
15
55
  * more (uploadTexture selects a frame by offset).
16
56
  */
17
- export function createMutableTexture(data: Uint8Array, width: number, height: number): number
57
+ export function createMutableTexture(data: Uint8Array, width: number, height: number, opts?: SamplerOptions): number
18
58
  /**
19
59
  * Replace a mutable texture's pixels. `data` may hold several frames; `offset`
20
60
  * (default 0) selects which frame to upload.
@@ -40,26 +80,118 @@ declare module "flux:gpu" {
40
80
  export function destroyTexture(id: number): void
41
81
  /**
42
82
  * Compile a GLSL ES fragment shader into an offscreen texture of the given
43
- * size. `params` sets float uniforms by name; `textures` binds sampler2D
44
- * uniforms to texture ids. Returns the resulting texture id.
83
+ * size. `params` sets uniforms by name (see {@link ShaderParams} for the
84
+ * value shapes); `textures` binds sampler2D uniforms to texture ids - any
85
+ * texture id, including another shader/pipeline target's output. Bound
86
+ * targets are live dependencies: when a source re-renders (its params,
87
+ * geometry, or data change), every target sampling it re-renders too,
88
+ * transitively through chains, before the next frame or readback - no
89
+ * per-frame uniform write is needed to keep a chain current. Returns the resulting texture id. The fused
90
+ * convenience: one call compiles a program and creates a target over it,
91
+ * and the program lives and dies with the target. To share one compile
92
+ * across targets (or hold a program with no target yet), use the raw layer:
93
+ * {@link compileShader} + {@link linkProgram} + {@link createShaderTarget}.
94
+ *
95
+ * The preamble (`#version 300 es`, precision, `vUV`, `iResolution`, `iTime`,
96
+ * `fragColor`) is injected only into sources that do not declare their own
97
+ * `#version` line. A source that starts with `#version 300 es` is compiled
98
+ * exactly as written, so a shader with its own uniform names (a port from
99
+ * elsewhere) needs no rewriting and no drop to the raw layer. The built-in
100
+ * vertex stage still supplies `vUV` to a complete source; declare
101
+ * `in vec2 vUV;` yourself to read it. Same rule on {@link createPipeline}.
102
+ * A complete source may also declare `iResolution` as vec3 (the Shadertoy
103
+ * shape); it is then filled as `(w, h, 1.0)`.
45
104
  */
46
105
  export function createShader(
47
106
  fragmentSrc: string,
48
107
  width: number,
49
108
  height: number,
50
- params?: Record<string, number>,
109
+ params?: ShaderParams,
51
110
  textures?: Record<string, number>,
111
+ opts?: SamplerOptions,
112
+ ): number
113
+ /**
114
+ * Compile a single shader stage from raw GLSL ES: the primitive under
115
+ * {@link linkProgram}, GL's own model (a "shader" is one stage; linking
116
+ * stages yields a program). The source is complete - it declares its own
117
+ * `#version 300 es`, precision, varyings and uniforms; nothing is injected.
118
+ * With `header: true` the standard header is prepended explicitly: `#version
119
+ * 300 es`, `precision highp float;`, `uniform vec2 iResolution;`, `uniform
120
+ * float iTime;`, plus `out vec4 fragColor;` for a fragment stage (the same
121
+ * text {@link createPipeline} injects). Do not combine `header` with your
122
+ * own `#version` line. Returns a shader (stage) id in its own id space;
123
+ * compile errors throw here, synchronously, at a call site the app chose.
124
+ * Free with {@link destroyShader}.
125
+ */
126
+ export function compileShader(
127
+ stage: "vertex" | "fragment",
128
+ source: string,
129
+ opts?: { header?: boolean },
130
+ ): number
131
+ /**
132
+ * Link a compiled vertex and fragment stage into a program, returning a
133
+ * program id (its own id space, like buffers - not a texture id). Link
134
+ * errors throw here. The stages remain usable for further links (mix one
135
+ * vertex stage with many fragment stages and vice versa), and may be
136
+ * destroyed right after: a linked program keeps its own compiled copies.
137
+ * Creating targets from the returned handle compiles nothing. Free with
138
+ * {@link destroyProgram}.
139
+ */
140
+ export function linkProgram(vertexShader: number, fragmentShader: number): number
141
+ /**
142
+ * Destroy a compiled stage by id. Programs linked from it are unaffected.
143
+ */
144
+ export function destroyShader(id: number): void
145
+ /**
146
+ * Create a render target over a linked program and render it once: the
147
+ * target half of {@link createPipeline}. Returns a texture id exactly like
148
+ * createShader/createPipeline do (drive uniforms via the `params` prop or
149
+ * {@link setShaderParams}, resize with {@link setShaderSize}, destroy with
150
+ * {@link destroyTexture}). Many targets may share one program. A raw-linked
151
+ * program carries its own vertex stage, so the mesh options apply:
152
+ * `attributes`/`buffer` for vertex input (omit for attributeless rendering
153
+ * via gl_VertexID - a fullscreen pass is `vertexCount: 3` with a
154
+ * covering-triangle vertex stage), `topology`, `vertexCount`, `depth`,
155
+ * `clearColor`, all as in {@link createPipeline}.
156
+ */
157
+ export function createShaderTarget(
158
+ program: number,
159
+ width: number,
160
+ height: number,
161
+ opts?: {
162
+ params?: ShaderParams
163
+ textures?: Record<string, number>
164
+ attributes?: VertexAttribute[]
165
+ buffer?: number
166
+ topology?: Topology
167
+ vertexCount?: number
168
+ depth?: boolean
169
+ depthWrite?: boolean
170
+ blend?: BlendMode
171
+ clearColor?: [number, number, number, number]
172
+ } & SamplerOptions,
52
173
  ): number
53
- /** Update a shader texture's float uniforms by name and re-render it. */
54
- export function setShaderParams(id: number, params: Record<string, number>): void
174
+ /**
175
+ * Destroy a linked program by id. Targets created from it are unaffected:
176
+ * each holds the program until it is itself destroyed, so either
177
+ * destruction order is safe. The id stops being usable for new targets
178
+ * immediately.
179
+ */
180
+ export function destroyProgram(id: number): void
181
+ /**
182
+ * Update a shader texture's uniforms by name and re-render it (see
183
+ * {@link ShaderParams} for the value shapes).
184
+ */
185
+ export function setShaderParams(id: number, params: ShaderParams): void
55
186
  /**
56
187
  * Rebind a shader texture's sampler2D inputs by uniform name and re-render
57
188
  * it with its last-applied params - the sampler analog of
58
189
  * {@link setShaderParams}. Bindings not named keep their current source, so
59
190
  * a single input can be retargeted (post-process source swap, ping-pong
60
191
  * between two data textures) without recompiling the shader. Throws if the
61
- * shader or a source texture id is unknown, or a sampler would source the
62
- * shader's own target.
192
+ * shader or a source texture id is unknown, or a binding would create a
193
+ * sampling cycle among targets (binding a shader's own target is the
194
+ * shortest case).
63
195
  */
64
196
  export function setShaderTextures(id: number, textures: Record<string, number>): void
65
197
  /**
@@ -71,6 +203,17 @@ declare module "flux:gpu" {
71
203
  export function setShaderSize(id: number, width: number, height: number): void
72
204
 
73
205
  export type Topology = "points" | "lines" | "line-strip" | "triangles" | "triangle-strip"
206
+ /**
207
+ * Blending for a pipeline's own draw. "none" (default) overwrites:
208
+ * overlapping geometry resolves by depth or draw order. "add" accumulates
209
+ * (glBlendFunc(ONE, ONE)): order-independent, so geometry needs no sorting
210
+ * - the additive half of translucency (point splats, glow passes). A
211
+ * depth-tested additive pass usually pairs with `depthWrite: false`; with
212
+ * writes on, unsorted geometry depth-rejects its own later fragments and
213
+ * accumulation becomes draw-order-dependent. That pairing is the app's to
214
+ * state - neither option implies the other.
215
+ */
216
+ export type BlendMode = "none" | "add"
74
217
  /**
75
218
  * One float attribute of an interleaved vertex. The attribute list's order
76
219
  * defines the byte layout; locations are resolved by name against the
@@ -86,8 +229,13 @@ declare module "flux:gpu" {
86
229
  * `buffer` (a {@link createBuffer} id); omit both for attributeless
87
230
  * rendering via gl_VertexID. `vertexCount` defaults to the whole buffer
88
231
  * (buffer size / vertex stride). With `depth: true` the pipeline gets a
89
- * private depth buffer, cleared and tested on every render. The target is
90
- * cleared to `clearColor` (default transparent black) before each draw.
232
+ * private depth buffer, cleared and tested on every render; `depthWrite:
233
+ * false` (requires `depth: true`) keeps the test but stops the draw from
234
+ * writing depth. `blend` sets the draw's own blending (see
235
+ * {@link BlendMode}); an additive pass over a depth buffer is
236
+ * `{ depth: true, blend: "add", depthWrite: false }`, stated explicitly.
237
+ * The target is cleared to `clearColor` (default transparent black) before
238
+ * each draw.
91
239
  * Returns a texture id: display it with `<texture src>`, drive uniforms via
92
240
  * the `params` prop or {@link setShaderParams}, destroy with
93
241
  * {@link destroyTexture}.
@@ -98,15 +246,17 @@ declare module "flux:gpu" {
98
246
  width: number,
99
247
  height: number,
100
248
  opts?: {
101
- params?: Record<string, number>
249
+ params?: ShaderParams
102
250
  textures?: Record<string, number>
103
251
  attributes?: VertexAttribute[]
104
252
  buffer?: number
105
253
  topology?: Topology
106
254
  vertexCount?: number
107
255
  depth?: boolean
256
+ depthWrite?: boolean
257
+ blend?: BlendMode
108
258
  clearColor?: [number, number, number, number]
109
- },
259
+ } & SamplerOptions,
110
260
  ): number
111
261
 
112
262
  /**
@@ -131,12 +281,34 @@ declare module "flux:gpu" {
131
281
  /**
132
282
  * Capture a render-tree node's subtree into a new GPU texture, resolving once
133
283
  * it has been rendered on the next paint pass. The node must be attached to
134
- * the live tree (a detached node is never painted, so its capture rejects).
284
+ * the live tree (an unmounted node is never painted, so its capture rejects)
285
+ * and paint a non-zero box. A laid-out node captures its layout box. A `d-*`
286
+ * node has no layout box - that is what detached means - so it captures its
287
+ * painted box instead: its own `w`/`h` when set, else the nearest laid-out
288
+ * ancestor's box (the same box the render tree reports for it), with its
289
+ * `x`/`y` paint offset mapped to the texture origin.
135
290
  * Rendered at the current display scale, so `width`/`height` are the texture's
136
291
  * actual pixel dimensions (ceil(logicalSize * displayScale)), not logical
137
292
  * points. Each call returns an independent id you must {@link destroyTexture}
138
293
  * when done. Use the returned id anywhere a texture id is accepted
139
294
  * (`<texture src>`, a shader sampler input, {@link readTexture}).
295
+ *
296
+ * Intended for one-shot bakes and inspection: turning something the engine
297
+ * can draw but the app cannot compute - shaped text, an SVG, a themed view -
298
+ * into pixels, usually to hand to {@link readTexture} and process on the CPU.
299
+ * Baking a glyph atlas by laying out cells, capturing them and keeping the
300
+ * coverage channel is the worked example. Tests and freeze-frames are the
301
+ * same shape.
302
+ *
303
+ * Not a rendering primitive. Every call rasterizes the subtree into a fresh
304
+ * offscreen MSAA target, reads the pixels back to the CPU and uploads them
305
+ * again as a new texture: a full GPU -> CPU -> GPU round trip plus a paint
306
+ * pass of latency, per call, with nothing incremental about it. Batch what
307
+ * you capture (many nodes captured together are serviced by one paint pass),
308
+ * and do not drive it per frame or reach for it to feed live content into a
309
+ * shader - an effect over what is beneath it, a backdrop filter. Content that
310
+ * must stay current has to come from a source that updates in place: another
311
+ * pipeline's render target, a camera texture, a mutable texture.
140
312
  */
141
313
  export function captureSnapshot(nodeId: number): Promise<{ id: number; width: number; height: number }>
142
314
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidrt/flux-types",
3
- "version": "0.0.38",
3
+ "version": "0.0.40",
4
4
  "license": "MIT",
5
5
  "author": "Antoine van Wel",
6
6
  "types": "index.d.ts",