@jbrowse/render-core 5.0.0-beta.7 → 5.0.0-beta.9
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/esm/RenderCanvas.d.ts +2 -2
- package/esm/RenderLifecycleMixin.d.ts +7 -6
- package/esm/RenderLifecycleMixin.js +7 -6
- package/esm/canvas2dUtils.d.ts +58 -17
- package/esm/canvas2dUtils.js +82 -30
- package/esm/computePipeline.d.ts +4 -3
- package/esm/computePipeline.js +21 -14
- package/esm/coverageBand.d.ts +3 -3
- package/esm/coverageBand.js +2 -2
- package/esm/coverageBandBuffers.d.ts +2 -3
- package/esm/createRenderingBackend.d.ts +1 -1
- package/esm/displayPhase.d.ts +79 -109
- package/esm/displayPhase.js +42 -83
- package/esm/gpuDevice.d.ts +11 -10
- package/esm/gpuDevice.js +10 -11
- package/esm/graphicsCapabilities.d.ts +6 -7
- package/esm/graphicsCapabilities.js +3 -4
- package/esm/hal/createHal.js +1 -1
- package/esm/hal/deviceGpuCache.d.ts +25 -30
- package/esm/hal/deviceGpuCache.js +85 -97
- package/esm/hal/index.d.ts +2 -2
- package/esm/hal/index.js +1 -1
- package/esm/hal/mockHal.d.ts +8 -6
- package/esm/hal/mockHal.js +7 -2
- package/esm/hal/passIds.d.ts +8 -7
- package/esm/hal/passIds.js +11 -10
- package/esm/hal/types.d.ts +28 -12
- package/esm/hal/webgl2Hal.d.ts +11 -3
- package/esm/hal/webgl2Hal.js +116 -145
- package/esm/hal/webgpuHal.d.ts +8 -8
- package/esm/hal/webgpuHal.js +97 -124
- package/esm/instancePass.d.ts +2 -1
- package/esm/mapUploadSync.d.ts +2 -2
- package/esm/mapUploadSync.js +2 -2
- package/esm/marks/barMark.d.ts +6 -3
- package/esm/marks/barMark.js +19 -13
- package/esm/marks/drawAgainstHit.d.ts +58 -39
- package/esm/marks/drawAgainstHit.js +136 -96
- package/esm/marks/glyphPaint.d.ts +14 -2
- package/esm/marks/glyphPaint.js +16 -2
- package/esm/marks/index.d.ts +4 -2
- package/esm/marks/index.js +3 -2
- package/esm/marks/markBackend.d.ts +2 -2
- package/esm/marks/markBackend.js +2 -2
- package/esm/marks/markHit.d.ts +2 -2
- package/esm/marks/markHit.js +2 -2
- package/esm/marks/markPlan.d.ts +2 -2
- package/esm/marks/markPlan.js +2 -2
- package/esm/marks/markRamp.d.ts +1 -3
- package/esm/marks/markRamp.js +1 -5
- package/esm/marks/nearestMarkHit.d.ts +49 -0
- package/esm/marks/nearestMarkHit.js +126 -0
- package/esm/marks/pointMark.d.ts +9 -2
- package/esm/marks/pointMark.js +36 -31
- package/esm/marks/rowLane.d.ts +17 -0
- package/esm/marks/rowLane.js +11 -0
- package/esm/marks/spanMark.d.ts +6 -26
- package/esm/marks/spanMark.js +34 -31
- package/esm/marks/types.d.ts +51 -181
- package/esm/marks/types.js +91 -131
- package/esm/namedReactions.d.ts +3 -4
- package/esm/namedReactions.js +3 -4
- package/esm/scoreScale.d.ts +20 -0
- package/esm/scoreScale.js +77 -0
- package/esm/shaders/barMark.generated.d.ts +2 -3
- package/esm/shaders/barMark.generated.js +4 -3
- package/esm/shaders/barMark.glsl.generated.d.ts +2 -0
- package/esm/shaders/barMark.glsl.generated.js +4 -0
- package/esm/shaders/barMark.iface.generated.d.ts +12 -6
- package/esm/shaders/barMark.iface.generated.js +27 -15
- package/esm/shaders/barMark.wgsl.generated.d.ts +1 -0
- package/esm/shaders/barMark.wgsl.generated.js +3 -0
- package/esm/shaders/coverageBar.generated.d.ts +2 -3
- package/esm/shaders/coverageBar.generated.js +4 -3
- package/esm/shaders/coverageBar.glsl.generated.d.ts +2 -0
- package/esm/shaders/coverageBar.glsl.generated.js +4 -0
- package/esm/shaders/coverageBar.iface.generated.js +1 -1
- package/esm/shaders/coverageBar.wgsl.generated.d.ts +1 -0
- package/esm/shaders/coverageBar.wgsl.generated.js +3 -0
- package/esm/shaders/coverageIndicator.generated.d.ts +2 -3
- package/esm/shaders/coverageIndicator.generated.js +4 -3
- package/esm/shaders/coverageIndicator.glsl.generated.d.ts +2 -0
- package/esm/shaders/coverageIndicator.glsl.generated.js +4 -0
- package/esm/shaders/coverageIndicator.iface.generated.js +1 -1
- package/esm/shaders/coverageIndicator.wgsl.generated.d.ts +1 -0
- package/esm/shaders/coverageIndicator.wgsl.generated.js +3 -0
- package/esm/shaders/coverageInterbase.generated.d.ts +2 -3
- package/esm/shaders/coverageInterbase.generated.js +4 -3
- package/esm/shaders/coverageInterbase.glsl.generated.d.ts +2 -0
- package/esm/shaders/coverageInterbase.glsl.generated.js +4 -0
- package/esm/shaders/coverageInterbase.iface.generated.js +1 -1
- package/esm/shaders/coverageInterbase.wgsl.generated.d.ts +1 -0
- package/esm/shaders/coverageInterbase.wgsl.generated.js +3 -0
- package/esm/shaders/coverageMod.generated.d.ts +2 -3
- package/esm/shaders/coverageMod.generated.js +4 -3
- package/esm/shaders/coverageMod.glsl.generated.d.ts +2 -0
- package/esm/shaders/coverageMod.glsl.generated.js +4 -0
- package/esm/shaders/coverageMod.iface.generated.js +1 -1
- package/esm/shaders/coverageMod.wgsl.generated.d.ts +1 -0
- package/esm/shaders/coverageMod.wgsl.generated.js +3 -0
- package/esm/shaders/coverageSnp.generated.d.ts +2 -3
- package/esm/shaders/coverageSnp.generated.js +4 -3
- package/esm/shaders/coverageSnp.glsl.generated.d.ts +2 -0
- package/esm/shaders/coverageSnp.glsl.generated.js +4 -0
- package/esm/shaders/coverageSnp.iface.generated.js +1 -1
- package/esm/shaders/coverageSnp.wgsl.generated.d.ts +1 -0
- package/esm/shaders/coverageSnp.wgsl.generated.js +3 -0
- package/esm/shaders/pointMark.generated.d.ts +2 -3
- package/esm/shaders/pointMark.generated.js +4 -3
- package/esm/shaders/pointMark.glsl.generated.d.ts +2 -0
- package/esm/shaders/pointMark.glsl.generated.js +4 -0
- package/esm/shaders/pointMark.iface.generated.d.ts +11 -3
- package/esm/shaders/pointMark.iface.generated.js +23 -9
- package/esm/shaders/pointMark.js.generated.d.ts +1 -1
- package/esm/shaders/pointMark.js.generated.js +51 -29
- package/esm/shaders/pointMark.wgsl.generated.d.ts +1 -0
- package/esm/shaders/pointMark.wgsl.generated.js +3 -0
- package/esm/shaders/scoreScale.js.generated.js +46 -22
- package/esm/shaders/spanMark.generated.d.ts +2 -3
- package/esm/shaders/spanMark.generated.js +4 -3
- package/esm/shaders/spanMark.glsl.generated.d.ts +2 -0
- package/esm/shaders/spanMark.glsl.generated.js +4 -0
- package/esm/shaders/spanMark.iface.generated.js +1 -1
- package/esm/shaders/spanMark.wgsl.generated.d.ts +1 -0
- package/esm/shaders/spanMark.wgsl.generated.js +3 -0
- package/esm/slangPass.d.ts +9 -10
- package/esm/slangPass.js +9 -3
- package/esm/useGraphicsCapabilities.d.ts +1 -1
- package/esm/useGraphicsCapabilities.js +1 -1
- package/esm/webgpuUtils.d.ts +3 -11
- package/esm/webgpuUtils.js +12 -33
- package/package.json +3 -2
- package/src/shaders/barMark.generated.ts +6 -5
- package/src/shaders/barMark.glsl.generated.ts +6 -0
- package/src/shaders/barMark.iface.generated.ts +31 -15
- package/src/shaders/barMark.slang +11 -3
- package/src/shaders/barMark.wgsl.generated.ts +4 -0
- package/src/shaders/colorPack.slang +3 -2
- package/src/shaders/coverageBand.slang +5 -11
- package/src/shaders/coverageBar.generated.ts +6 -5
- package/src/shaders/coverageBar.glsl.generated.ts +6 -0
- package/src/shaders/coverageBar.iface.generated.ts +1 -1
- package/src/shaders/coverageBar.slang +1 -1
- package/src/shaders/coverageBar.wgsl.generated.ts +4 -0
- package/src/shaders/coverageIndicator.generated.ts +6 -5
- package/src/shaders/coverageIndicator.glsl.generated.ts +6 -0
- package/src/shaders/coverageIndicator.iface.generated.ts +1 -1
- package/src/shaders/coverageIndicator.wgsl.generated.ts +4 -0
- package/src/shaders/coverageInterbase.generated.ts +6 -5
- package/src/shaders/coverageInterbase.glsl.generated.ts +6 -0
- package/src/shaders/coverageInterbase.iface.generated.ts +1 -1
- package/src/shaders/coverageInterbase.wgsl.generated.ts +4 -0
- package/src/shaders/coverageMod.generated.ts +6 -5
- package/src/shaders/coverageMod.glsl.generated.ts +6 -0
- package/src/shaders/coverageMod.iface.generated.ts +1 -1
- package/src/shaders/coverageMod.wgsl.generated.ts +4 -0
- package/src/shaders/coverageSnp.generated.ts +6 -5
- package/src/shaders/coverageSnp.glsl.generated.ts +6 -0
- package/src/shaders/coverageSnp.iface.generated.ts +1 -1
- package/src/shaders/coverageSnp.wgsl.generated.ts +4 -0
- package/src/shaders/hpmath.slang +18 -6
- package/src/shaders/pointMark.generated.ts +6 -6
- package/src/shaders/pointMark.glsl.generated.ts +6 -0
- package/src/shaders/pointMark.iface.generated.ts +28 -9
- package/src/shaders/pointMark.js.generated.ts +48 -29
- package/src/shaders/pointMark.slang +18 -5
- package/src/shaders/pointMark.wgsl.generated.ts +4 -0
- package/src/shaders/scoreScale.js.generated.ts +43 -22
- package/src/shaders/scoreScale.slang +37 -53
- package/src/shaders/spanMark.generated.ts +6 -5
- package/src/shaders/spanMark.glsl.generated.ts +6 -0
- package/src/shaders/spanMark.iface.generated.ts +1 -1
- package/src/shaders/spanMark.wgsl.generated.ts +4 -0
- package/src/shaders/valueScale.slang +8 -45
package/esm/displayPhase.d.ts
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The mutually-exclusive visual state of a GPU display. Computing it in one
|
|
3
|
-
* place means the precedence — renderError > tooLarge > error >
|
|
4
|
-
* — lives in a single function instead of being re-encoded by
|
|
5
|
-
* (`&& !regionTooLarge && !error && !renderError`) in every display
|
|
6
|
-
* mirrored a second time by `DisplayChrome`'s JSX order.
|
|
7
|
-
* switches on it; the loading scrim's visibility is just
|
|
8
|
-
* `displayPhase === 'loading'`, computed once in the chrome.
|
|
3
|
+
* place means the precedence — renderError > tooLarge > error > canceled >
|
|
4
|
+
* loading > ready — lives in a single function instead of being re-encoded by
|
|
5
|
+
* subtraction (`&& !regionTooLarge && !error && !renderError`) in every display
|
|
6
|
+
* model AND mirrored a second time by `DisplayChrome`'s JSX order.
|
|
9
7
|
*
|
|
10
8
|
* `renderError` and `tooLarge` replace the whole display subtree (their own
|
|
11
9
|
* root element, so the transition unmounts the canvas → `canvasRef(null)` →
|
|
12
|
-
* `backend.dispose()`). `error` and `loading` are overlays rendered
|
|
13
|
-
* still-mounted canvas, so they share the `ready` branch's root.
|
|
10
|
+
* `backend.dispose()`). `error`, `canceled` and `loading` are overlays rendered
|
|
11
|
+
* *over* the still-mounted canvas, so they share the `ready` branch's root.
|
|
12
|
+
*
|
|
13
|
+
* `loading` is the one phase that means work is outstanding: every reader
|
|
14
|
+
* asking "is it finished" (`AppReadyMarker`, `jb.waitReady`, the capture waits)
|
|
15
|
+
* treats every other phase as finished. `canceled` is the user's standing stop,
|
|
16
|
+
* durable until Retry (or, on the LGV families, a viewport change); the chrome
|
|
17
|
+
* draws it as the loading overlay in its canceled state, which carries Retry.
|
|
14
18
|
*/
|
|
15
19
|
export type DisplayPhase = 'renderError' | DisplayStatusPhase;
|
|
16
20
|
/**
|
|
@@ -20,10 +24,14 @@ export type DisplayPhase = 'renderError' | DisplayStatusPhase;
|
|
|
20
24
|
* (the backend hook's `retry()`), which is exactly the line between the shared
|
|
21
25
|
* status chrome and the GPU chrome wrapped around it: `DisplayStatusChrome`
|
|
22
26
|
* takes this, `DisplayChrome` takes the wider union and peels off `renderError`
|
|
23
|
-
* before delegating.
|
|
24
|
-
|
|
27
|
+
* before delegating.
|
|
28
|
+
*/
|
|
29
|
+
export type DisplayStatusPhase = 'tooLarge' | 'error' | DisplayActivityPhase;
|
|
30
|
+
/**
|
|
31
|
+
* What is left once no failure terminal holds, as `computeActivityPhase`
|
|
32
|
+
* answers it for every fetching family.
|
|
25
33
|
*/
|
|
26
|
-
export type
|
|
34
|
+
export type DisplayActivityPhase = 'canceled' | 'loading' | 'ready';
|
|
27
35
|
export interface DisplayStatusPhaseInputs {
|
|
28
36
|
regionTooLarge: boolean;
|
|
29
37
|
error: unknown;
|
|
@@ -32,133 +40,95 @@ export interface DisplayPhaseInputs extends DisplayStatusPhaseInputs {
|
|
|
32
40
|
renderError: unknown;
|
|
33
41
|
}
|
|
34
42
|
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* layers a zoom gate on top. The terminal precedence above it is identical for
|
|
38
|
-
* every display, so it lives here — pass the display's loading condition and
|
|
39
|
-
* get the resolved phase back.
|
|
43
|
+
* The terminal precedence shared by every display, over the display's own
|
|
44
|
+
* activity phase.
|
|
40
45
|
*
|
|
41
|
-
* `
|
|
42
|
-
* ruled out.
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* React-reconciliation hazard documented in DisplayChrome.tsx). Short-circuiting
|
|
49
|
-
* keeps the tracked set to just the terminal flags when one is active, matching
|
|
50
|
-
* the old direct-read early-returns.
|
|
46
|
+
* `activity` is a **thunk**, evaluated only after the three failure terminals
|
|
47
|
+
* are ruled out. Load-bearing for MobX: the activity condition typically reads
|
|
48
|
+
* the containing view (`visibleRegions`, `loadedRegions`, …), and evaluating it
|
|
49
|
+
* eagerly would subscribe every reader of `displayPhase` to that churn even
|
|
50
|
+
* while a banner is up — and `DisplayChrome`'s observer, re-firing during a
|
|
51
|
+
* terminal state, then fails to commit the banner subtree (see
|
|
52
|
+
* DisplayChrome.tsx).
|
|
51
53
|
*/
|
|
52
|
-
export declare function computeDisplayPhase({ renderError, regionTooLarge, error }: DisplayPhaseInputs,
|
|
54
|
+
export declare function computeDisplayPhase({ renderError, regionTooLarge, error }: DisplayPhaseInputs, activity: () => DisplayActivityPhase): DisplayPhase;
|
|
53
55
|
/**
|
|
54
|
-
* The
|
|
55
|
-
*
|
|
56
|
-
*
|
|
56
|
+
* The terms the activity phase is built from, minus the thunks. All cheap flags
|
|
57
|
+
* on the display itself, so they are read eagerly the same way
|
|
58
|
+
* `computeDisplayPhase` reads its terminals.
|
|
57
59
|
*/
|
|
58
|
-
export interface
|
|
60
|
+
export interface DisplayActivityInputs {
|
|
61
|
+
/**
|
|
62
|
+
* The containing track is minimized. Every fetch gate skips a minimized
|
|
63
|
+
* track and its canvas is unmounted, so nothing the terms below wait on can
|
|
64
|
+
* arrive. Suppresses them all, like `fetchInert`, which a subclass overrides
|
|
65
|
+
* outright and so cannot carry it.
|
|
66
|
+
*/
|
|
67
|
+
isMinimized: boolean;
|
|
59
68
|
/**
|
|
60
69
|
* The display is deliberately showing a static message instead of data
|
|
61
|
-
* (sequence past base resolution, LD with the triangle off)
|
|
62
|
-
*
|
|
63
|
-
* not a substitute: that one drops the pre-first-paint term alone
|
|
64
|
-
* fetch terms free to scrim over the placeholder, and `isLoadingOrCanceled`
|
|
65
|
-
* includes a cancel that is deliberately durable.
|
|
70
|
+
* (sequence past base resolution, LD with the triangle off). Suppresses every
|
|
71
|
+
* term below, a standing cancel included — which is why `rendersCanvas: false`
|
|
72
|
+
* is not a substitute: that one drops the pre-first-paint term alone.
|
|
66
73
|
*/
|
|
67
74
|
fetchInert: boolean;
|
|
68
75
|
/**
|
|
69
|
-
* The view holds no content block
|
|
70
|
-
*
|
|
71
|
-
* `
|
|
72
|
-
* `viewportEmpty`). Suppresses every term below for the same reason
|
|
73
|
-
* `fetchInert` does, and it is the pre-first-paint one that makes it
|
|
74
|
-
* necessary: no fetch is issued, so `canvasDrawn` is never set and the scrim
|
|
75
|
-
* would sit there for as long as the viewport stays off content.
|
|
76
|
+
* The view holds no content block (`showAllRegions` over a region set whose
|
|
77
|
+
* every member falls under `minimumBlockWidth`; see `viewportEmpty`), so no
|
|
78
|
+
* fetch is issued and `canvasDrawn` is never set. Suppresses every term below.
|
|
76
79
|
*/
|
|
77
80
|
viewportEmpty: boolean;
|
|
81
|
+
/** a fetch is in flight */
|
|
82
|
+
isLoading: boolean;
|
|
78
83
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
+
* The user canceled a fetch and has not retried. Outranks every loading term,
|
|
85
|
+
* since what those wait on is the fetch the user stopped. Kept apart from
|
|
86
|
+
* `isLoading` because a cancel is finished, not pending: folded into the
|
|
87
|
+
* loading term, a canceled display read `loading` until Retry and parked every
|
|
88
|
+
* readiness gate on it.
|
|
84
89
|
*/
|
|
85
|
-
|
|
90
|
+
fetchCanceled: boolean;
|
|
86
91
|
/**
|
|
87
92
|
* A load this display depends on beyond its primary fetch has not landed for
|
|
88
|
-
* the first time
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* drawn is the thing a display saying this wants to avoid.
|
|
93
|
+
* the first time (multi-way synteny's lane genes and links). A loading term
|
|
94
|
+
* rather than a `dataSuperseded` fold: that flag holds the export through
|
|
95
|
+
* every later refetch too, and a scrim over lanes already drawn is the thing
|
|
96
|
+
* a display saying this wants to avoid.
|
|
93
97
|
*/
|
|
94
98
|
awaitingDependentData: boolean;
|
|
95
99
|
/**
|
|
96
100
|
* Whether this display paints a canvas in its current configuration. Gates
|
|
97
|
-
* the pre-first-paint term alone, because a display
|
|
98
|
-
*
|
|
99
|
-
* `canvasDrawn` and would sit under the scrim forever.
|
|
101
|
+
* the pre-first-paint term alone, because a display showing a deliberate
|
|
102
|
+
* non-canvas placeholder (LD with the triangle off) never flips `canvasDrawn`.
|
|
100
103
|
*/
|
|
101
104
|
rendersCanvas: boolean;
|
|
102
105
|
/** first paint has happened */
|
|
103
106
|
canvasDrawn: boolean;
|
|
104
107
|
}
|
|
105
108
|
/**
|
|
106
|
-
* The
|
|
107
|
-
*
|
|
109
|
+
* The activity phase, expressed once for every fetching display family, so a
|
|
110
|
+
* term added here reaches every display. The two LGV families hand-wrote it
|
|
111
|
+
* until they had drifted on the cancel term and on which suppression hook each
|
|
112
|
+
* carried.
|
|
108
113
|
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* exactly one of the two suppression hooks — `fetchInert` on per-region,
|
|
114
|
-
* `rendersCanvas` on global — so a display in the other family could express its
|
|
115
|
-
* case only by overriding `displayPhase`, which is the thing both hooks exist to
|
|
116
|
-
* prevent. Single-sourcing the expression is the same argument the precedence
|
|
117
|
-
* above already won, one level down: a term added here reaches every display,
|
|
118
|
-
* instead of reaching whichever family the author happened to be reading.
|
|
119
|
-
*
|
|
120
|
-
* The four inputs all now live on a mixin every foundation composes —
|
|
121
|
-
* `fetchInert` / `isLoadingOrCanceled` on `FetchMixin`, `rendersCanvas` /
|
|
122
|
-
* `canvasDrawn` on `RenderLifecycleMixin` — so `foundationDisplayPhase` passes
|
|
123
|
-
* the model straight through and the only thing a family supplies is
|
|
124
|
-
* `viewportCurrent`: per-region its staleness predicate, global `() => true` (it
|
|
125
|
-
* keeps the last frame up through a refetch rather than scrimming). Two hooks
|
|
126
|
-
* used to be hard-coded per family instead, which is how the second drift
|
|
127
|
-
* happened after the first was fixed — LD needed `fetchInert` and the
|
|
128
|
-
* global family did not have it.
|
|
129
|
-
*
|
|
130
|
-
* `viewportCurrent` is a **thunk** for the same MobX reason `computeDisplayPhase`'s
|
|
131
|
-
* `loading` is: it reads the containing view (`visibleRegions`, `loadedRegions`),
|
|
132
|
-
* while the flag inputs above are on the display itself. Short-circuiting keeps a
|
|
133
|
-
* suppressed or already-loading display from subscribing to viewport churn.
|
|
114
|
+
* `viewportCurrent` is a **thunk** for the MobX reason `computeDisplayPhase`'s
|
|
115
|
+
* `activity` is: it reads the containing view, while the flags above are on the
|
|
116
|
+
* display. Per-region passes its staleness predicate, global `() => true` (it
|
|
117
|
+
* keeps the last frame up through a refetch rather than scrimming).
|
|
134
118
|
*
|
|
135
119
|
* `hostMounted` is a thunk for the same reason, and gates the **pre-first-paint
|
|
136
|
-
* term only**.
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
* It is a required flag on every view and on the duck-typed host contracts, not
|
|
144
|
-
* an optional one defaulted here: a stand-in that forgot it would silently
|
|
145
|
-
* excuse the first paint and let a readiness gate fire over a view that had not
|
|
146
|
-
* started.
|
|
147
|
-
*
|
|
148
|
-
* The fetch terms deliberately stay live while unmounted: an off-screen display
|
|
149
|
-
* still fetches, so reporting it idle would let a readiness gate fire over work
|
|
150
|
-
* genuinely in flight — and during cold load `visible` is false until the
|
|
151
|
-
* IntersectionObserver's first callback, which is exactly when a display must
|
|
152
|
-
* not flash `ready`. Only the paint it will never do is excused.
|
|
120
|
+
* term only**. `ViewContainer` mounts an off-screen view's body lazily, so its
|
|
121
|
+
* display has no canvas and `!canvasDrawn` could never resolve — which parked
|
|
122
|
+
* `[data-app-phase="ready"]` for the whole app. It is required on every view and
|
|
123
|
+
* host contract rather than defaulted there, so a stand-in has to state it and
|
|
124
|
+
* cannot excuse the first paint by omission. The fetch terms stay live while unmounted: an
|
|
125
|
+
* off-screen display still fetches, and during cold load `visible` is false
|
|
126
|
+
* until the IntersectionObserver's first callback.
|
|
153
127
|
*/
|
|
154
|
-
export declare function
|
|
128
|
+
export declare function computeActivityPhase({ isMinimized, fetchInert, viewportEmpty, isLoading, fetchCanceled, awaitingDependentData, rendersCanvas, canvasDrawn, }: DisplayActivityInputs, viewportCurrent: () => boolean, hostMounted?: () => boolean): DisplayActivityPhase;
|
|
155
129
|
/**
|
|
156
130
|
* The same ranking minus `renderError`, for a display with no rendering backend
|
|
157
|
-
* to fail (arc's main-thread SVG). `computeDisplayPhase` delegates here
|
|
158
|
-
*
|
|
159
|
-
* and the narrower return type is what lets `DisplayStatusChrome` accept a
|
|
160
|
-
* backend-less display without either a cast or a dead branch.
|
|
161
|
-
*
|
|
162
|
-
* `loading` is a thunk here for the same reason as above.
|
|
131
|
+
* to fail (arc's main-thread SVG). `computeDisplayPhase` delegates here, so the
|
|
132
|
+
* order lives in one place.
|
|
163
133
|
*/
|
|
164
|
-
export declare function computeDisplayStatusPhase({ regionTooLarge, error }: DisplayStatusPhaseInputs,
|
|
134
|
+
export declare function computeDisplayStatusPhase({ regionTooLarge, error }: DisplayStatusPhaseInputs, activity: () => DisplayActivityPhase): DisplayStatusPhase;
|
package/esm/displayPhase.js
CHANGED
|
@@ -1,98 +1,57 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* would make every reader of `displayPhase` subscribe to all of it even while a
|
|
13
|
-
* banner is up — and `DisplayChrome`'s observer, re-firing on that churn during
|
|
14
|
-
* a terminal state, then fails to commit the banner subtree to the DOM (the
|
|
15
|
-
* React-reconciliation hazard documented in DisplayChrome.tsx). Short-circuiting
|
|
16
|
-
* keeps the tracked set to just the terminal flags when one is active, matching
|
|
17
|
-
* the old direct-read early-returns.
|
|
2
|
+
* The terminal precedence shared by every display, over the display's own
|
|
3
|
+
* activity phase.
|
|
4
|
+
*
|
|
5
|
+
* `activity` is a **thunk**, evaluated only after the three failure terminals
|
|
6
|
+
* are ruled out. Load-bearing for MobX: the activity condition typically reads
|
|
7
|
+
* the containing view (`visibleRegions`, `loadedRegions`, …), and evaluating it
|
|
8
|
+
* eagerly would subscribe every reader of `displayPhase` to that churn even
|
|
9
|
+
* while a banner is up — and `DisplayChrome`'s observer, re-firing during a
|
|
10
|
+
* terminal state, then fails to commit the banner subtree (see
|
|
11
|
+
* DisplayChrome.tsx).
|
|
18
12
|
*/
|
|
19
|
-
export function computeDisplayPhase({ renderError, regionTooLarge, error },
|
|
13
|
+
export function computeDisplayPhase({ renderError, regionTooLarge, error }, activity) {
|
|
20
14
|
return renderError
|
|
21
15
|
? 'renderError'
|
|
22
|
-
: computeDisplayStatusPhase({ regionTooLarge, error },
|
|
16
|
+
: computeDisplayStatusPhase({ regionTooLarge, error }, activity);
|
|
23
17
|
}
|
|
24
18
|
/**
|
|
25
|
-
* The
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* three ways that were equivalent only by accident: the per-region family spelled
|
|
30
|
-
* the cancel term out by hand (`!isReady || … || fetchCanceled`, over a bare
|
|
31
|
-
* `isLoading`) rather than reading `isLoadingOrCanceled`, and each family carried
|
|
32
|
-
* exactly one of the two suppression hooks — `fetchInert` on per-region,
|
|
33
|
-
* `rendersCanvas` on global — so a display in the other family could express its
|
|
34
|
-
* case only by overriding `displayPhase`, which is the thing both hooks exist to
|
|
35
|
-
* prevent. Single-sourcing the expression is the same argument the precedence
|
|
36
|
-
* above already won, one level down: a term added here reaches every display,
|
|
37
|
-
* instead of reaching whichever family the author happened to be reading.
|
|
38
|
-
*
|
|
39
|
-
* The four inputs all now live on a mixin every foundation composes —
|
|
40
|
-
* `fetchInert` / `isLoadingOrCanceled` on `FetchMixin`, `rendersCanvas` /
|
|
41
|
-
* `canvasDrawn` on `RenderLifecycleMixin` — so `foundationDisplayPhase` passes
|
|
42
|
-
* the model straight through and the only thing a family supplies is
|
|
43
|
-
* `viewportCurrent`: per-region its staleness predicate, global `() => true` (it
|
|
44
|
-
* keeps the last frame up through a refetch rather than scrimming). Two hooks
|
|
45
|
-
* used to be hard-coded per family instead, which is how the second drift
|
|
46
|
-
* happened after the first was fixed — LD needed `fetchInert` and the
|
|
47
|
-
* global family did not have it.
|
|
19
|
+
* The activity phase, expressed once for every fetching display family, so a
|
|
20
|
+
* term added here reaches every display. The two LGV families hand-wrote it
|
|
21
|
+
* until they had drifted on the cancel term and on which suppression hook each
|
|
22
|
+
* carried.
|
|
48
23
|
*
|
|
49
|
-
* `viewportCurrent` is a **thunk** for the
|
|
50
|
-
* `
|
|
51
|
-
*
|
|
52
|
-
*
|
|
24
|
+
* `viewportCurrent` is a **thunk** for the MobX reason `computeDisplayPhase`'s
|
|
25
|
+
* `activity` is: it reads the containing view, while the flags above are on the
|
|
26
|
+
* display. Per-region passes its staleness predicate, global `() => true` (it
|
|
27
|
+
* keeps the last frame up through a refetch rather than scrimming).
|
|
53
28
|
*
|
|
54
29
|
* `hostMounted` is a thunk for the same reason, and gates the **pre-first-paint
|
|
55
|
-
* term only**.
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* It is a required flag on every view and on the duck-typed host contracts, not
|
|
63
|
-
* an optional one defaulted here: a stand-in that forgot it would silently
|
|
64
|
-
* excuse the first paint and let a readiness gate fire over a view that had not
|
|
65
|
-
* started.
|
|
66
|
-
*
|
|
67
|
-
* The fetch terms deliberately stay live while unmounted: an off-screen display
|
|
68
|
-
* still fetches, so reporting it idle would let a readiness gate fire over work
|
|
69
|
-
* genuinely in flight — and during cold load `visible` is false until the
|
|
70
|
-
* IntersectionObserver's first callback, which is exactly when a display must
|
|
71
|
-
* not flash `ready`. Only the paint it will never do is excused.
|
|
30
|
+
* term only**. `ViewContainer` mounts an off-screen view's body lazily, so its
|
|
31
|
+
* display has no canvas and `!canvasDrawn` could never resolve — which parked
|
|
32
|
+
* `[data-app-phase="ready"]` for the whole app. It is required on every view and
|
|
33
|
+
* host contract rather than defaulted there, so a stand-in has to state it and
|
|
34
|
+
* cannot excuse the first paint by omission. The fetch terms stay live while unmounted: an
|
|
35
|
+
* off-screen display still fetches, and during cold load `visible` is false
|
|
36
|
+
* until the IntersectionObserver's first callback.
|
|
72
37
|
*/
|
|
73
|
-
export function
|
|
74
|
-
return
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
38
|
+
export function computeActivityPhase({ isMinimized, fetchInert, viewportEmpty, isLoading, fetchCanceled, awaitingDependentData, rendersCanvas, canvasDrawn, }, viewportCurrent, hostMounted = () => true) {
|
|
39
|
+
return isMinimized || fetchInert || viewportEmpty
|
|
40
|
+
? 'ready'
|
|
41
|
+
: fetchCanceled
|
|
42
|
+
? 'canceled'
|
|
43
|
+
: isLoading ||
|
|
44
|
+
awaitingDependentData ||
|
|
45
|
+
(rendersCanvas && hostMounted() && !canvasDrawn) ||
|
|
46
|
+
!viewportCurrent()
|
|
47
|
+
? 'loading'
|
|
48
|
+
: 'ready';
|
|
80
49
|
}
|
|
81
50
|
/**
|
|
82
51
|
* The same ranking minus `renderError`, for a display with no rendering backend
|
|
83
|
-
* to fail (arc's main-thread SVG). `computeDisplayPhase` delegates here
|
|
84
|
-
*
|
|
85
|
-
* and the narrower return type is what lets `DisplayStatusChrome` accept a
|
|
86
|
-
* backend-less display without either a cast or a dead branch.
|
|
87
|
-
*
|
|
88
|
-
* `loading` is a thunk here for the same reason as above.
|
|
52
|
+
* to fail (arc's main-thread SVG). `computeDisplayPhase` delegates here, so the
|
|
53
|
+
* order lives in one place.
|
|
89
54
|
*/
|
|
90
|
-
export function computeDisplayStatusPhase({ regionTooLarge, error },
|
|
91
|
-
return regionTooLarge
|
|
92
|
-
? 'tooLarge'
|
|
93
|
-
: error
|
|
94
|
-
? 'error'
|
|
95
|
-
: loading()
|
|
96
|
-
? 'loading'
|
|
97
|
-
: 'ready';
|
|
55
|
+
export function computeDisplayStatusPhase({ regionTooLarge, error }, activity) {
|
|
56
|
+
return regionTooLarge ? 'tooLarge' : error ? 'error' : activity();
|
|
98
57
|
}
|
package/esm/gpuDevice.d.ts
CHANGED
|
@@ -5,7 +5,8 @@ interface GpuDeviceCell {
|
|
|
5
5
|
devicePromise: Promise<GPUDevice | null> | null;
|
|
6
6
|
/**
|
|
7
7
|
* Proof that this machine's WebGPU works, set the first time a device is
|
|
8
|
-
* acquired.
|
|
8
|
+
* acquired. The flag tells the two causes of a failed acquisition apart,
|
|
9
|
+
* because the two
|
|
9
10
|
* causes are indistinguishable at the call site and want opposite handling:
|
|
10
11
|
*
|
|
11
12
|
* - Before it, failure means "no WebGPU here" — the ordinary path on most
|
|
@@ -16,9 +17,9 @@ interface GpuDeviceCell {
|
|
|
16
17
|
* `requestAdapter` still declines. So this is not a rare race — it is the
|
|
17
18
|
* expected timing of the one path that re-acquires.
|
|
18
19
|
*
|
|
19
|
-
*
|
|
20
|
-
* this machine" (its own words)
|
|
21
|
-
*
|
|
20
|
+
* `createGpuHal` reads a cached failure of the second kind as "no WebGPU on
|
|
21
|
+
* this machine" (its own words) and pins the whole page to WebGL2 until a
|
|
22
|
+
* reload. So past this flag a failure is retried and never cached.
|
|
22
23
|
*/
|
|
23
24
|
hadDevice: boolean;
|
|
24
25
|
deviceLostListeners: Set<() => void>;
|
|
@@ -46,10 +47,10 @@ export declare function onDeviceLost(listener: () => void): () => void;
|
|
|
46
47
|
* The renderers `?renderer=` can pin the page to. `canvas` is a spelling of
|
|
47
48
|
* `canvas2d` kept because it is in the wild.
|
|
48
49
|
*
|
|
49
|
-
* A pin means *only* that rung — `createGpuHal` does not fall past it.
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
50
|
+
* A pin means *only* that rung — `createGpuHal` does not fall past it. The flag
|
|
51
|
+
* is for comparing backends, and a comparison that renders with a different
|
|
52
|
+
* backend than the one pinned is worse than no comparison. The failure shows
|
|
53
|
+
* instead, as a `renderError` carrying the pin that could
|
|
53
54
|
* not be honored, with the banner's "disable GPU" as the way out.
|
|
54
55
|
*/
|
|
55
56
|
export declare const GPU_OVERRIDES: readonly ['webgpu', 'webgl', 'canvas2d', 'canvas'];
|
|
@@ -63,8 +64,8 @@ export type GpuOverride = (typeof GPU_OVERRIDES)[number];
|
|
|
63
64
|
* `--renderer` flag), so validating here is validating once at the only place
|
|
64
65
|
* an unchecked value enters. An unrecognized one clears the pin and says so:
|
|
65
66
|
* before this, `?renderer=WebGL` or a typo was indistinguishable from passing
|
|
66
|
-
* nothing at all,
|
|
67
|
-
*
|
|
67
|
+
* nothing at all, and a person debugging a renderer got the default ladder
|
|
68
|
+
* with no sign the pin was ignored.
|
|
68
69
|
*/
|
|
69
70
|
export declare function setGpuOverride(value: string | null): void;
|
|
70
71
|
export declare function getGpuOverride(): string | null;
|
package/esm/gpuDevice.js
CHANGED
|
@@ -11,13 +11,12 @@
|
|
|
11
11
|
* button on the context-loss banner, which `packages/render-core/CLAUDE.md`
|
|
12
12
|
* names as the only sanctioned fallback path once a backend is built.
|
|
13
13
|
*
|
|
14
|
-
* A
|
|
15
|
-
*
|
|
16
|
-
*
|
|
14
|
+
* A plugin that bundled render-core is the case this exists for. Every plugin
|
|
15
|
+
* built before ADR-128 did, so a third-party display can carry its own copy of
|
|
16
|
+
* this module; with module locals its `gpuOverride` would start
|
|
17
17
|
* null and stay null, and the user who pins `?renderer=canvas2d` or clicks
|
|
18
18
|
* "disable GPU" after a crash would watch the plugin ignore both and take
|
|
19
|
-
* WebGPU anyway. Sharing the cell fixes that
|
|
20
|
-
* frozen `ReExports` ABI — which is the trade ADR-030 declined, and rightly.
|
|
19
|
+
* WebGPU anyway. Sharing the cell fixes that for every copy, served or bundled.
|
|
21
20
|
*
|
|
22
21
|
* **The shape is a cross-version contract.** Copies at different render-core
|
|
23
22
|
* versions meet here, and whichever loads first wins the initialization, so a
|
|
@@ -188,10 +187,10 @@ async function createDevice() {
|
|
|
188
187
|
* The renderers `?renderer=` can pin the page to. `canvas` is a spelling of
|
|
189
188
|
* `canvas2d` kept because it is in the wild.
|
|
190
189
|
*
|
|
191
|
-
* A pin means *only* that rung — `createGpuHal` does not fall past it.
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
190
|
+
* A pin means *only* that rung — `createGpuHal` does not fall past it. The flag
|
|
191
|
+
* is for comparing backends, and a comparison that renders with a different
|
|
192
|
+
* backend than the one pinned is worse than no comparison. The failure shows
|
|
193
|
+
* instead, as a `renderError` carrying the pin that could
|
|
195
194
|
* not be honored, with the banner's "disable GPU" as the way out.
|
|
196
195
|
*/
|
|
197
196
|
export const GPU_OVERRIDES = ['webgpu', 'webgl', 'canvas2d', 'canvas'];
|
|
@@ -207,8 +206,8 @@ function isGpuOverride(value) {
|
|
|
207
206
|
* `--renderer` flag), so validating here is validating once at the only place
|
|
208
207
|
* an unchecked value enters. An unrecognized one clears the pin and says so:
|
|
209
208
|
* before this, `?renderer=WebGL` or a typo was indistinguishable from passing
|
|
210
|
-
* nothing at all,
|
|
211
|
-
*
|
|
209
|
+
* nothing at all, and a person debugging a renderer got the default ladder
|
|
210
|
+
* with no sign the pin was ignored.
|
|
212
211
|
*/
|
|
213
212
|
export function setGpuOverride(value) {
|
|
214
213
|
if (value !== null && !isGpuOverride(value)) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export interface GraphicsCapabilities {
|
|
2
2
|
webgpu: boolean;
|
|
3
3
|
/**
|
|
4
|
-
* `undefined` when the WebGL2 probe was skipped
|
|
5
|
-
*
|
|
4
|
+
* `undefined` when the WebGL2 probe was skipped. `getGraphicsCapabilities`
|
|
5
|
+
* skips it whenever WebGPU answered first — see there.
|
|
6
6
|
*/
|
|
7
7
|
webgl2?: boolean;
|
|
8
8
|
gpuVendor?: string;
|
|
@@ -29,8 +29,8 @@ export interface GraphicsCapabilities {
|
|
|
29
29
|
* The rungs of the rendering ladder, as the names a person reads — the About
|
|
30
30
|
* widget's "Graphics:" line, the stack-trace dialog, the analytics field.
|
|
31
31
|
*
|
|
32
|
-
* Deliberately *not* the {@link GpuOverride} vocabulary,
|
|
33
|
-
* types into `?renderer
|
|
32
|
+
* Deliberately *not* the {@link GpuOverride} vocabulary, the values a user
|
|
33
|
+
* types into `?renderer=`, which therefore carry lowercase spellings and the
|
|
34
34
|
* `webgl`/`canvas` aliases. One is an input to parse, the other an answer to
|
|
35
35
|
* display, and collapsing them would mean either showing "canvas2d" in the UI
|
|
36
36
|
* or accepting "Canvas2D" in a URL.
|
|
@@ -77,9 +77,8 @@ export declare function getGraphicsCapabilities(): Promise<GraphicsCapabilities>
|
|
|
77
77
|
* The Canvas2D pin is checked ahead of the record because the banner's
|
|
78
78
|
* "disable GPU" sets it before the displays rebuild on the new rung. The other
|
|
79
79
|
* pins win outright in the prediction, because **a pin never falls through to
|
|
80
|
-
* the next rung** — `createGpuHal` throws instead,
|
|
81
|
-
*
|
|
82
|
-
* against it wrong. So the pinned rung *is* the answer, and a pin that cannot
|
|
80
|
+
* the next rung** — `createGpuHal` throws instead, because a pinned renderer
|
|
81
|
+
* that falls back to another rung makes any comparison against it wrong. So the pinned rung *is* the answer, and a pin that cannot
|
|
83
82
|
* be honored surfaces as a `renderError` rather than as a different string
|
|
84
83
|
* here. The one case the prediction cannot resolve from capabilities alone
|
|
85
84
|
* (`?renderer=webgl` on a WebGPU machine, where the WebGL2 probe was skipped)
|
|
@@ -50,7 +50,7 @@ async function probeWebgpu() {
|
|
|
50
50
|
* that call is effectively driver-wide (ADR-005 removed it from
|
|
51
51
|
* `WebGL2Hal.dispose()` for the same reason), so probing while tracks were on
|
|
52
52
|
* screen knocked out their live sibling contexts — and both browsers log the
|
|
53
|
-
* loss to the console,
|
|
53
|
+
* loss to the console, where a user sees it. The canvas is unreachable the
|
|
54
54
|
* moment this returns and the browser reclaims the context on GC, the same
|
|
55
55
|
* release the HAL relies on. A page that then reaches the 16-context ceiling
|
|
56
56
|
* evicts this one first (it is the oldest, and nothing draws to it or
|
|
@@ -123,9 +123,8 @@ export function getGraphicsCapabilities() {
|
|
|
123
123
|
* The Canvas2D pin is checked ahead of the record because the banner's
|
|
124
124
|
* "disable GPU" sets it before the displays rebuild on the new rung. The other
|
|
125
125
|
* pins win outright in the prediction, because **a pin never falls through to
|
|
126
|
-
* the next rung** — `createGpuHal` throws instead,
|
|
127
|
-
*
|
|
128
|
-
* against it wrong. So the pinned rung *is* the answer, and a pin that cannot
|
|
126
|
+
* the next rung** — `createGpuHal` throws instead, because a pinned renderer
|
|
127
|
+
* that falls back to another rung makes any comparison against it wrong. So the pinned rung *is* the answer, and a pin that cannot
|
|
129
128
|
* be honored surfaces as a `renderError` rather than as a different string
|
|
130
129
|
* here. The one case the prediction cannot resolve from capabilities alone
|
|
131
130
|
* (`?renderer=webgl` on a WebGPU machine, where the WebGL2 probe was skipped)
|
package/esm/hal/createHal.js
CHANGED
|
@@ -91,7 +91,7 @@ async function climbLadder(canvas, { passes, sampleCount, failures }) {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
try {
|
|
94
|
-
return
|
|
94
|
+
return await WebGL2Hal.create(canvas, passes);
|
|
95
95
|
}
|
|
96
96
|
catch (e) {
|
|
97
97
|
console.warn('[GPU] WebGL2 unavailable, falling back to Canvas2D:', e);
|
|
@@ -1,36 +1,31 @@
|
|
|
1
|
-
import type { PipelineDescriptor, SampleCount } from './types.ts';
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* not worth the null-bundling for two objects per *device*.
|
|
7
|
-
*/
|
|
8
|
-
export interface DeviceLayouts {
|
|
9
|
-
uniformOnlyBindGroupLayout: GPUBindGroupLayout;
|
|
10
|
-
uniformOnlyPipelineLayout: GPUPipelineLayout;
|
|
11
|
-
texturedBindGroupLayout: GPUBindGroupLayout;
|
|
12
|
-
texturedPipelineLayout: GPUPipelineLayout;
|
|
1
|
+
import type { PipelineDescriptor, SampleCount, ShaderBinding } from './types.ts';
|
|
2
|
+
/** A pass's one bind-group layout, and the pipeline layout holding it as group 0. */
|
|
3
|
+
export interface PassLayout {
|
|
4
|
+
bindGroupLayout: GPUBindGroupLayout;
|
|
5
|
+
pipelineLayout: GPUPipelineLayout;
|
|
13
6
|
}
|
|
14
7
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* new object, so the layouts and pipelines built against the dead one are
|
|
20
|
-
* unreachable and there is no cache to invalidate by hand.
|
|
8
|
+
* A render pass's bind-group layout, read off its shader's reflected table:
|
|
9
|
+
* each binding visible to exactly the stages that read it, so the layout
|
|
10
|
+
* cannot disagree with the shader about which stage reads what. The uniform
|
|
11
|
+
* block takes a dynamic offset into the HAL's ring.
|
|
21
12
|
*/
|
|
22
|
-
export declare function
|
|
13
|
+
export declare function bindGroupLayoutEntries(bindings: readonly ShaderBinding[]): GPUBindGroupLayoutEntry[];
|
|
23
14
|
/**
|
|
24
|
-
*
|
|
25
|
-
* `
|
|
26
|
-
*
|
|
27
|
-
* `build` receives the sample count rather than closing over one, so the key
|
|
28
|
-
* and the pipeline stored under it cannot disagree.
|
|
29
|
-
*/
|
|
30
|
-
export declare function getOrBuildPipeline(device: GPUDevice, desc: PipelineDescriptor, sampleCount: SampleCount, build: (layouts: DeviceLayouts, sampleCount: SampleCount) => Promise<GPURenderPipeline>): Promise<GPURenderPipeline>;
|
|
31
|
-
/**
|
|
32
|
-
* Drop every device's entry. Tests only — nothing in the app invalidates this
|
|
33
|
-
* cache, because losing the device is what invalidates it (see
|
|
34
|
-
* {@link getDeviceLayouts}).
|
|
15
|
+
* What a pipeline is compiled from and cached under: `WebGPUHal` builds from
|
|
16
|
+
* nothing else. `uniformByteSize` stays out, since the layouts declare no
|
|
17
|
+
* `minBindingSize`, and so does the page-wide canvas format.
|
|
35
18
|
*/
|
|
19
|
+
export interface PipelineRecipe {
|
|
20
|
+
wgslSource: string;
|
|
21
|
+
bindGroupLayout: GPUBindGroupLayoutEntry[];
|
|
22
|
+
vertexBuffer: GPUVertexBufferLayout;
|
|
23
|
+
blend: GPUBlendState | undefined;
|
|
24
|
+
topology: GPUPrimitiveTopology;
|
|
25
|
+
/** Baked in: a pipeline built at 4 draws nothing into a target at 1. */
|
|
26
|
+
sampleCount: SampleCount;
|
|
27
|
+
}
|
|
28
|
+
export declare function pipelineRecipe(desc: PipelineDescriptor, wgslSource: string, sampleCount: SampleCount): PipelineRecipe;
|
|
29
|
+
export declare function getPassLayout(device: GPUDevice, entries: GPUBindGroupLayoutEntry[]): PassLayout;
|
|
30
|
+
export declare function getOrBuildPipeline(device: GPUDevice, recipe: PipelineRecipe, build: (recipe: PipelineRecipe) => Promise<GPURenderPipeline>): Promise<GPURenderPipeline>;
|
|
36
31
|
export declare function resetDeviceGpuCacheForTests(device: GPUDevice): void;
|