@photivra/engine 2.10.0 → 2.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +156 -1
- package/CITATION.cff +1 -1
- package/NODE_SUPPORT.md +19 -3
- package/README.md +6 -6
- package/SECURITY.md +1 -1
- package/dist/core/portable-math.d.ts +6 -0
- package/dist/core/portable-math.js +39 -0
- package/dist/core/portable-math.js.map +1 -1
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/dist/core/version.js.map +1 -1
- package/dist/facade/chart-material-layers.d.ts +115 -0
- package/dist/facade/chart-material-layers.js +224 -0
- package/dist/facade/chart-material-layers.js.map +1 -0
- package/dist/facade/chart-radiance-batch.d.ts +8 -2
- package/dist/facade/chart-radiance-batch.js +11 -4
- package/dist/facade/chart-radiance-batch.js.map +1 -1
- package/dist/facade/chart-scenes.d.ts +134 -0
- package/dist/facade/chart-scenes.js +32 -22
- package/dist/facade/chart-scenes.js.map +1 -1
- package/dist/facade/diffraction-provider.d.ts +8 -2
- package/dist/facade/diffraction-provider.js +71 -2
- package/dist/facade/diffraction-provider.js.map +1 -1
- package/dist/facade/display-view-gpu-session.d.ts +18 -0
- package/dist/facade/display-view-gpu-session.js +280 -0
- package/dist/facade/display-view-gpu-session.js.map +1 -0
- package/dist/facade/display-view-gpu.d.ts +146 -0
- package/dist/facade/display-view-gpu.js +59 -0
- package/dist/facade/display-view-gpu.js.map +1 -0
- package/dist/facade/display-view.d.ts +48 -1
- package/dist/facade/display-view.js +7 -7
- package/dist/facade/display-view.js.map +1 -1
- package/dist/facade/expected-signal-setup.d.ts +5 -0
- package/dist/facade/expected-signal-setup.js +16 -0
- package/dist/facade/expected-signal-setup.js.map +1 -1
- package/dist/facade/expected-signal.d.ts +48 -3
- package/dist/facade/expected-signal.js +8 -0
- package/dist/facade/expected-signal.js.map +1 -1
- package/dist/facade/scene-radiance.d.ts +4 -2
- package/dist/facade/scene-radiance.js +7 -4
- package/dist/facade/scene-radiance.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +108 -8
- package/dist/facade/simulate-capture.js +226 -33
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/facade/simulate-display-view.d.ts +31 -3
- package/dist/facade/simulate-display-view.js +73 -13
- package/dist/facade/simulate-display-view.js.map +1 -1
- package/dist/gpu/chart-composite-gpu.d.ts +119 -0
- package/dist/gpu/chart-composite-gpu.js +572 -0
- package/dist/gpu/chart-composite-gpu.js.map +1 -0
- package/dist/gpu/chart-radiance-gpu.d.ts +6 -6
- package/dist/gpu/chart-radiance-gpu.js +9 -11
- package/dist/gpu/chart-radiance-gpu.js.map +1 -1
- package/dist/gpu/display-view-chart-material-module.d.ts +10 -0
- package/dist/gpu/display-view-chart-material-module.js +58 -0
- package/dist/gpu/display-view-chart-material-module.js.map +1 -0
- package/dist/gpu/display-view-composite-material-module.d.ts +68 -0
- package/dist/gpu/display-view-composite-material-module.js +248 -0
- package/dist/gpu/display-view-composite-material-module.js.map +1 -0
- package/dist/gpu/display-view-quality-gpu.d.ts +185 -0
- package/dist/gpu/display-view-quality-gpu.js +1000 -0
- package/dist/gpu/display-view-quality-gpu.js.map +1 -0
- package/dist/gpu/display-view-speed-gpu.d.ts +156 -0
- package/dist/gpu/display-view-speed-gpu.js +524 -0
- package/dist/gpu/display-view-speed-gpu.js.map +1 -0
- package/dist/gpu/image-kernel-accelerator.d.ts +23 -4
- package/dist/gpu/image-kernel-accelerator.js +58 -10
- package/dist/gpu/image-kernel-accelerator.js.map +1 -1
- package/dist/gpu/image-kernel-execution.d.ts +55 -3
- package/dist/gpu/image-kernel-execution.js.map +1 -1
- package/dist/gpu/sensor-stage-gpu.d.ts +11 -0
- package/dist/gpu/sensor-stage-gpu.js +42 -13
- package/dist/gpu/sensor-stage-gpu.js.map +1 -1
- package/dist/gpu/webgpu-runtime.d.ts +4 -2
- package/dist/gpu/webgpu-runtime.js +13 -4
- package/dist/gpu/webgpu-runtime.js.map +1 -1
- package/dist/gpu/webgpu-switch.d.ts +4 -0
- package/dist/gpu/webgpu-switch.js +29 -0
- package/dist/gpu/webgpu-switch.js.map +1 -0
- package/dist/gpu/wgsl-chart-composite-kernel.d.ts +52 -0
- package/dist/gpu/wgsl-chart-composite-kernel.js +515 -0
- package/dist/gpu/wgsl-chart-composite-kernel.js.map +1 -0
- package/dist/gpu/wgsl-chart-kernel.d.ts +11 -9
- package/dist/gpu/wgsl-chart-kernel.js +33 -27
- package/dist/gpu/wgsl-chart-kernel.js.map +1 -1
- package/dist/gpu/wgsl-display-view-quality-kernel.d.ts +95 -0
- package/dist/gpu/wgsl-display-view-quality-kernel.js +769 -0
- package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -0
- package/dist/gpu/wgsl-display-view-speed-kernel.d.ts +75 -0
- package/dist/gpu/wgsl-display-view-speed-kernel.js +386 -0
- package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -0
- package/dist/gpu/wgsl-sensor-kernel.d.ts +28 -9
- package/dist/gpu/wgsl-sensor-kernel.js +94 -50
- package/dist/gpu/wgsl-sensor-kernel.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/optics/defocus-disc-kernel.d.ts +61 -0
- package/dist/optics/defocus-disc-kernel.js +191 -0
- package/dist/optics/defocus-disc-kernel.js.map +1 -0
- package/docs/API_REFERENCE.md +47 -1
- package/docs/QUICK_START.md +150 -5
- package/docs/USAGE.md +81 -3
- package/docs/api/core-version.md +1 -1
- package/docs/api/exports.json +127 -2
- package/docs/api/facade-chart-material-layers.md +137 -0
- package/docs/api/facade-chart-radiance-batch.md +7 -2
- package/docs/api/facade-display-view-gpu.md +94 -0
- package/docs/api/facade-scene-radiance.md +3 -2
- package/docs/api/facade-simulate-capture.md +95 -11
- package/docs/api/facade-simulate-display-view.md +17 -2
- package/docs/api/gpu-image-kernel-accelerator.md +10 -3
- package/docs/api/gpu-image-kernel-execution.md +71 -4
- package/docs/api/gpu-webgpu-switch.md +23 -0
- package/package.json +3 -1
|
@@ -21,8 +21,10 @@ export interface DisplayViewResult {
|
|
|
21
21
|
*/
|
|
22
22
|
view: { width: number; height: number; frameWidth: number; frameHeight: number; scaleX: number; scaleY: number; samplesPerAxis: number;
|
|
23
23
|
region?: { x: number; y: number; width: number; height: number } };
|
|
24
|
-
/** The resolved exposure of the capture this view shows. */
|
|
25
|
-
exposure: { mode: SimulateCaptureExposureMode; settings: { fNumber: number; shutterSeconds: number; iso: number }; ev100: number
|
|
24
|
+
/** The resolved exposure of the capture this view shows; `standardExposureDeviationStops` as in {@link SimulateCaptureResult}. */
|
|
25
|
+
exposure: { mode: SimulateCaptureExposureMode; settings: { fNumber: number; shutterSeconds: number; iso: number }; ev100: number; standardExposureDeviationStops: number | null;
|
|
26
|
+
/** #516: as in the capture result. */
|
|
27
|
+
isoControl: "manual" | "automatic"; autoIso?: SimulateCaptureAutoIsoReport };
|
|
26
28
|
scene: SimulateCaptureResult["scene"];
|
|
27
29
|
/**
|
|
28
30
|
* Work done: real pixels sampled, real-site expectations evaluated, scene queries, display pixels sampled in full (detail) or with
|
|
@@ -31,8 +33,8 @@ export interface DisplayViewResult {
|
|
|
31
33
|
*/
|
|
32
34
|
diagnostics: { sampleCount: number; siteEvaluations: number; sceneLookups: number; detailPixelCount: number; uniformPixelCount: number; ahdCorrectedPixelCount: number;
|
|
33
35
|
timingsMs: { view: number; total: number };
|
|
34
|
-
/** #395: exact or fast, as requested and as run (see {@link
|
|
35
|
-
fast:
|
|
36
|
+
/** #395: exact or fast, as requested and as run; 2.11 (#481): plus `execution`, where the render ran (see {@link DisplayViewFastReport}). */
|
|
37
|
+
fast: DisplayViewFastReport };
|
|
36
38
|
provenance: { scientificStatus: "approximation"; cameraPresetId: string; cameraPresetVersion: string; evidence: readonly EvidenceProvenance[];
|
|
37
39
|
composedContracts: readonly string[]; limitations: readonly string[] };
|
|
38
40
|
/** The capture request's assumptions, then `view.definition`, `view.estimation`, `view.noise`, `view.demosaic` and `view.source`. */
|
|
@@ -53,7 +55,9 @@ export interface IdealReferenceResult {
|
|
|
53
55
|
engineApiVersion: string;
|
|
54
56
|
image: { width: number; height: number; format: SimulateCaptureOutputFormat; samples: Uint8Array | Uint16Array; png?: Uint8Array; colorEncoding?: SimulateCaptureColorEncoding };
|
|
55
57
|
/** The resolved exposure of the capture this reference matches. */
|
|
56
|
-
exposure: { mode: SimulateCaptureExposureMode; settings: { fNumber: number; shutterSeconds: number; iso: number }; ev100: number
|
|
58
|
+
exposure: { mode: SimulateCaptureExposureMode; settings: { fNumber: number; shutterSeconds: number; iso: number }; ev100: number;
|
|
59
|
+
/** #516: as in the capture result. */
|
|
60
|
+
isoControl: "manual" | "automatic"; autoIso?: SimulateCaptureAutoIsoReport };
|
|
57
61
|
scene: SimulateCaptureResult["scene"];
|
|
58
62
|
region?: { x: number; y: number; width: number; height: number; frameWidth: number; frameHeight: number };
|
|
59
63
|
diagnostics: { sampleCount: number; timingsMs: { reference: number; total: number } };
|
|
@@ -96,7 +100,7 @@ a capture does. `motion.rotation` is a non-zero angular velocity; `sensor.tempor
|
|
|
96
100
|
|
|
97
101
|
```ts
|
|
98
102
|
SIMULATE_CAPTURE_COST_OPTIONS = Object.freeze(["lens.pupilSampling", "lens.projection", "lens.distortion", "lens.vignetting", "lens.psf",
|
|
99
|
-
"lens.diffraction", "sensor.antiAliasing", "sensor.pixelAperture.box", "sensor.temporalSampleCount", "motion.rotation", "motion.shutter.rolling", "output.borderHandling.mirror", "output.region",
|
|
103
|
+
"lens.diffraction", "lens.defocus", "sensor.antiAliasing", "sensor.pixelAperture.box", "sensor.temporalSampleCount", "motion.rotation", "motion.shutter.rolling", "output.borderHandling.mirror", "output.region",
|
|
100
104
|
"output.whiteBalance.auto", "output.demosaic.ahd", "output.highlightMode.reconstruct", "output.colorEncoding.wide-gamut", "output.gamutMapping.perceptual",
|
|
101
105
|
"output.format.jpeg", "output.format.png", "output.format.dng"] as const)
|
|
102
106
|
```
|
|
@@ -163,6 +167,45 @@ export interface SimulateCaptureAssumption {
|
|
|
163
167
|
}
|
|
164
168
|
```
|
|
165
169
|
|
|
170
|
+
## SimulateCaptureAutoIsoAfterMaximum
|
|
171
|
+
|
|
172
|
+
#516: what aperture priority does with Auto ISO once the ISO reaches the body's Auto ISO maximum and the exposure is
|
|
173
|
+
still under the meter target: `"allow-slower-shutter"` lengthens the shutter past the slowest preferred shutter to reach
|
|
174
|
+
the target; `"hold-preferred-shutter"` keeps the preferred shutter and leaves the exposure under target.
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
export type SimulateCaptureAutoIsoAfterMaximum = "allow-slower-shutter" | "hold-preferred-shutter";
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## SimulateCaptureAutoIsoReport
|
|
181
|
+
|
|
182
|
+
#516: how Auto ISO chose the ISO (`exposure.iso: "auto"`), reported in the result's `exposure.autoIso`. The full
|
|
183
|
+
resolver output stays in the capture's `exposure.resolution`.
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
export interface SimulateCaptureAutoIsoReport {
|
|
187
|
+
/** The ISO the meter target asked for at the resolved aperture and shutter, before the Auto ISO range and the ISO grid. */
|
|
188
|
+
idealIsoBeforeConstraints: number;
|
|
189
|
+
/** The Auto ISO range the ISO was chosen in: the body's Auto ISO bounds, or its ISO range when it declares none (the tiers: ISO 100 to their maximum). */
|
|
190
|
+
autoIsoMinimum: number;
|
|
191
|
+
autoIsoMaximum: number;
|
|
192
|
+
/** Whether the ISO was held at an end of the Auto ISO range. */
|
|
193
|
+
clamped: false | "minimum" | "maximum";
|
|
194
|
+
/**
|
|
195
|
+
* The constraint that limited the resolved exposure: the resolver's `targetResidual.limitingConstraint`, for example
|
|
196
|
+
* `"iso-maximum"` (the exposure stays under target at the Auto ISO maximum), `"iso-grid-quantization"` (the nearest
|
|
197
|
+
* selectable ISO) or `"none"` (on target).
|
|
198
|
+
*/
|
|
199
|
+
limitingConstraint: ExposureResolutionConstraint;
|
|
200
|
+
/** The resolver's residual, log2(target / achieved exposure), in stops: positive when the exposure is under the meter target, negative when over it. */
|
|
201
|
+
residualStops: number;
|
|
202
|
+
/** Aperture priority only: the policy and slowest preferred shutter used, and whether the slower-shutter fallback ran. */
|
|
203
|
+
afterMaximumIso?: SimulateCaptureAutoIsoAfterMaximum;
|
|
204
|
+
slowestPreferredShutterSeconds?: number;
|
|
205
|
+
afterMaximumIsoFallbackUsed?: boolean;
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
166
209
|
## SimulateCaptureBorderHandling
|
|
167
210
|
|
|
168
211
|
`margin` renders extra native sites around the output, as far as the kernel reaches. `mirror` renders
|
|
@@ -323,19 +366,47 @@ export interface SimulateCaptureOptions {
|
|
|
323
366
|
* the longest spectral node, capped at 32 sites. Not combinable with `psf` or `pupilSampling`. Default off.
|
|
324
367
|
*/
|
|
325
368
|
diffraction?: SimulateCaptureLensDiffraction;
|
|
369
|
+
/**
|
|
370
|
+
* Opt-in (#492): defocus of the flat scene plane when `focusDistanceM` differs from the subject distance, as a
|
|
371
|
+
* geometric disc (`model: "geometric-disc"`): the thin-lens blur circle of an ideal uniform circular pupil
|
|
372
|
+
* (`calculateDefocusCircle`), an approximation. The blur diameter is recorded in the `lens.defocus` assumption.
|
|
373
|
+
* `simulateCapture` renders the blur as an object-space convolution of the scene radiance on the site lattice and
|
|
374
|
+
* `simulateDisplayView` as a site kernel in its expected signal; with `diffraction` each spectral node's diffraction
|
|
375
|
+
* kernel is convolved with the disc (a further approximation). In focus the result is that of the same request
|
|
376
|
+
* without the option, plus the assumption.
|
|
377
|
+
* Not combinable with `pupilSampling` or `psf`. Default off.
|
|
378
|
+
*/
|
|
379
|
+
defocus?: { model: "geometric-disc" };
|
|
326
380
|
};
|
|
327
381
|
exposure?: {
|
|
328
382
|
/** Default "manual". */
|
|
329
383
|
mode?: SimulateCaptureExposureMode;
|
|
330
|
-
/**
|
|
331
|
-
|
|
384
|
+
/**
|
|
385
|
+
* Default 100. #516: `"auto"` lets the body's Auto ISO choose the ISO from the meter target, within its Auto ISO range
|
|
386
|
+
* (the tiers: ISO 100 to their maximum), in every mode: manual keeps the aperture and shutter; aperture priority keeps the
|
|
387
|
+
* aperture and follows `autoIso`; shutter priority picks the aperture at the lowest Auto ISO (no wider than the target
|
|
388
|
+
* needs, so at most the widest) and raises the ISO for the rest; program picks the program line at the lowest Auto ISO and
|
|
389
|
+
* raises the ISO beyond the line's end. The result reports the ISO in `exposure.settings.iso` and how it was chosen in
|
|
390
|
+
* `exposure.autoIso`.
|
|
391
|
+
*/
|
|
392
|
+
iso?: number | "auto";
|
|
393
|
+
/**
|
|
394
|
+
* #516: aperture priority with `iso: "auto"` only (required there). The shutter gets as long as
|
|
395
|
+
* `slowestPreferredShutterSeconds` (seconds, within the body's shutter range) at the lowest Auto ISO; beyond it the ISO
|
|
396
|
+
* rises; at the Auto ISO maximum `afterMaximumIso` decides (default `"allow-slower-shutter"`).
|
|
397
|
+
*/
|
|
398
|
+
autoIso?: { slowestPreferredShutterSeconds: number; afterMaximumIso?: SimulateCaptureAutoIsoAfterMaximum };
|
|
332
399
|
/** Shutter for manual and shutter-priority modes. Default 1/125 s. */
|
|
333
400
|
shutterSeconds?: number;
|
|
334
401
|
/** Exposure compensation applied to the meter target, in stops. Default 0. */
|
|
335
402
|
compensationStops?: number;
|
|
336
403
|
};
|
|
337
|
-
/**
|
|
338
|
-
|
|
404
|
+
/**
|
|
405
|
+
* Required: an engine chart (for example `{ preset: "uniform" }`, an 18 % grey card), a declared `material-layers` scene (#491:
|
|
406
|
+
* a chart under shape-mask layers, as `resolveChartMaterialLayers` takes it; the capture is that of its `callerScene`, byte for
|
|
407
|
+
* byte, and the display view can render it on the GPU), or a caller reflectance, radiance or material function.
|
|
408
|
+
*/
|
|
409
|
+
scene: ChartScene | ChartMaterialLayerScene | CallerReflectanceScene | CallerRadianceScene | CallerMaterialScene;
|
|
339
410
|
/** Distance from the camera to the scene plane in metres. Default 5. */
|
|
340
411
|
subjectDistanceM?: number;
|
|
341
412
|
/**
|
|
@@ -533,7 +604,18 @@ export interface SimulateCaptureResult {
|
|
|
533
604
|
settings: { fNumber: number; shutterSeconds: number; iso: number };
|
|
534
605
|
/** Exposure value at ISO 100 of the settings, log2(N²/t). */
|
|
535
606
|
ev100: number;
|
|
607
|
+
/** #516: `"automatic"` when the request asked for `iso: "auto"`, else `"manual"`. */
|
|
608
|
+
isoControl: "manual" | "automatic";
|
|
609
|
+
/** #516: present with `iso: "auto"`: how Auto ISO chose `settings.iso` and what limited it. */
|
|
610
|
+
autoIso?: SimulateCaptureAutoIsoReport;
|
|
536
611
|
meteredSceneLuminanceCdPerSquareMeter: number;
|
|
612
|
+
/**
|
|
613
|
+
* #515: deviation, in stops, of the exposure used from the CIPA DC-004-2020 standard exposure for the metered luminance L:
|
|
614
|
+
* log2(N²/t) − log2(0.65·L·S/10). Positive is darker than the standard exposure (under), negative brighter (over). In an
|
|
615
|
+
* automatic mode it is the compensation with the opposite sign plus any step or limit the resolver hit. Finite, or null when
|
|
616
|
+
* the metered luminance is 0 (a black scene has no standard exposure).
|
|
617
|
+
*/
|
|
618
|
+
standardExposureDeviationStops: number | null;
|
|
537
619
|
/** Full output of the existing exposure-mode resolver. */
|
|
538
620
|
resolution: unknown;
|
|
539
621
|
};
|
|
@@ -574,8 +656,10 @@ export interface SimulateCaptureResult {
|
|
|
574
656
|
* `diffraction` (the object-space convolution of `lens.diffraction`; part of `raw` and `whiteBalance`), `demosaic`
|
|
575
657
|
* (the AHD demosaic; part of `development`) and `encode` (PNG, JPEG or DNG serialization), with sub-millisecond
|
|
576
658
|
* resolution where the host has `performance.now()`. Timings vary from run to run and never enter any digest or output byte.
|
|
659
|
+
* #492: `defocus`, the object-space convolution of `lens.defocus` out of focus (with `lens.diffraction` the combined
|
|
660
|
+
* kernel's convolution, reported here instead of under `diffraction`).
|
|
577
661
|
*/
|
|
578
|
-
timingsMs: { raw: number; whiteBalance: number; development: number; jpeg: number; total: number; diffraction?: number; demosaic?: number; encode?: number };
|
|
662
|
+
timingsMs: { raw: number; whiteBalance: number; development: number; jpeg: number; total: number; diffraction?: number; defocus?: number; demosaic?: number; encode?: number };
|
|
579
663
|
/**
|
|
580
664
|
* 2.1: the opt-in options that changed the work of this run, in a fixed order (see `SIMULATE_CAPTURE_COST_OPTIONS`).
|
|
581
665
|
* Empty for a capture with every default. With `timingsMs` it lets an application measure each option's cost on
|
|
@@ -13,9 +13,17 @@ setup: use it to render one view in many regions, for example on each worker of
|
|
|
13
13
|
export interface PreparedDisplayView {
|
|
14
14
|
/**
|
|
15
15
|
* Renders a view of the prepared request. Renders may run concurrently; they share no state except read-only setup and the
|
|
16
|
-
* realm's AHD correction states, which never change a byte (docs/DISPLAY_VIEW.md, "AHD at low signal").
|
|
16
|
+
* realm's AHD correction states, which never change a byte (docs/DISPLAY_VIEW.md, "AHD at low signal"). With `gpu: "auto"`
|
|
17
|
+
* or `"require"` (#481) GPU renders of one prepared view run one at a time on its device, and `diagnostics.fast.execution`
|
|
18
|
+
* says whether the GPU or the CPU reference rendered the view, and why.
|
|
17
19
|
*/
|
|
18
20
|
render(view: SimulateDisplayViewOptions, renderOptions?: PreparedDisplayViewRenderOptions): Promise<DisplayViewResult>;
|
|
21
|
+
/**
|
|
22
|
+
* 2.11 (#481): releases the WebGPU device the view acquired (none with `gpu: "off"`, or when `gpuDevice` gave an accelerator,
|
|
23
|
+
* whose device its owner keeps). Later renders run the CPU reference labelled `fallbackReason: "disposed"` (`"auto"`) or fail
|
|
24
|
+
* with that reason (`"require"`). Idempotent.
|
|
25
|
+
*/
|
|
26
|
+
dispose(): void;
|
|
19
27
|
/**
|
|
20
28
|
* 2.10 (#447): the key of this request's AHD low-signal correction states, or null when the request has no AHD
|
|
21
29
|
* (`output.demosaic` other than "ahd"). Every input of the key is fixed when the request is prepared; two prepared views
|
|
@@ -57,8 +65,15 @@ responses through the environment chain, the diffraction kernels, readout moment
|
|
|
57
65
|
about 0.3–1.3 s per call on a 24 MP request; a region costs only its own pixels. Errors in the request are raised here;
|
|
58
66
|
errors in the view by `render`.
|
|
59
67
|
|
|
68
|
+
2.11 (#481): `prepareOptions.gpu` chooses the renderer: `"off"` (default) is the CPU reference, today's bytes; `"auto"` renders
|
|
69
|
+
on WebGPU when a conforming device is available and the request is supported, else on the CPU, labelled; `"require"` fails
|
|
70
|
+
instead of falling back (`ImageKernelExecutionError`, acquisition failures here, later ones from `render`). `gpuDevice` is a
|
|
71
|
+
WebGPU entry point or an `ImageKernelAccelerator` whose device the view shares; without it the engine acquires one device
|
|
72
|
+
for the prepared view (the request's `signal` aborts the acquisition) and `dispose()` releases it. The realm's
|
|
73
|
+
`setWebGpuEnabled(false)` vetoes both GPU modes (`webgpu-disabled`). See docs/DISPLAY_VIEW.md, "Rendering on the GPU".
|
|
74
|
+
|
|
60
75
|
```ts
|
|
61
|
-
export async function prepareDisplayView(options: SimulateCaptureOptions): Promise<PreparedDisplayView>;
|
|
76
|
+
export async function prepareDisplayView(options: SimulateCaptureOptions, prepareOptions?: PrepareDisplayViewOptions): Promise<PreparedDisplayView>;
|
|
62
77
|
```
|
|
63
78
|
|
|
64
79
|
This call is asynchronous; byte hashing uses the caller runtime's Web Crypto.
|
|
@@ -71,6 +71,8 @@ export interface ImageKernelAccelerator {
|
|
|
71
71
|
readonly backend: ImageKernelBackend;
|
|
72
72
|
readonly requestedBackend: ImageKernelBackend;
|
|
73
73
|
readonly fallbackReason: ImageKernelFallbackReason | null;
|
|
74
|
+
/** #481: the adapter of a `webgpu-f32` accelerator's device (null for `cpu-reference`, or when the browser gives no `GPUAdapter.info`). */
|
|
75
|
+
readonly adapter: ImageKernelAdapterDescription | null;
|
|
74
76
|
readonly state: ImageKernelAcceleratorState;
|
|
75
77
|
renderNativeCaptureSdr(input: NativeCaptureSdrInput, provider: NativeCaptureSdrProvider, options?: ImageKernelRunOptions): Promise<AcceleratedNativeCaptureSdrOutput>;
|
|
76
78
|
/** Takes ownership of `input.raw` exactly like `createNativeRawDevelopmentTask` (the caller's arrays are detached). */
|
|
@@ -93,9 +95,14 @@ The exact contract is declared below; use the domain guide for assumptions and s
|
|
|
93
95
|
|
|
94
96
|
```ts
|
|
95
97
|
export interface ImageKernelAcceleratorOptions {
|
|
96
|
-
/**
|
|
97
|
-
|
|
98
|
-
|
|
98
|
+
/**
|
|
99
|
+
* The one-boolean form. `true` is `backend: "webgpu-f32"` with `fallback: "cpu-reference"` unless `fallback` is given;
|
|
100
|
+
* `false` is `backend: "cpu-reference"`. Give `webgpu` or `backend`, not both.
|
|
101
|
+
*/
|
|
102
|
+
webgpu?: boolean;
|
|
103
|
+
/** Requested backend. `cpu-reference` is the reference and never touches WebGPU. Required unless `webgpu` is given. */
|
|
104
|
+
backend?: ImageKernelBackend;
|
|
105
|
+
/** Required with `backend: "webgpu-f32"`: use the CPU reference (labelled) or fail when WebGPU cannot be acquired. */
|
|
99
106
|
fallback?: "cpu-reference" | "fail";
|
|
100
107
|
/** WebGPU entry point; defaults to `navigator.gpu`. Supply a worker's `navigator.gpu` explicitly if needed. */
|
|
101
108
|
gpu?: unknown;
|
|
@@ -2,6 +2,58 @@
|
|
|
2
2
|
|
|
3
3
|
The package and root API versions are recorded once in [Navigation](../API_REFERENCE.md) · [Developer guide](https://github.com/Photivra/photivra/blob/main/docs/DEVELOPERS.md). Generated signatures retain independent schema/model versions. Only the exports listed here are root-package contracts; module-local helpers are not supported deep imports.
|
|
4
4
|
|
|
5
|
+
## ChartCompositeProbeComponent
|
|
6
|
+
|
|
7
|
+
A component of the composite chart kernel's double-float32 probe (see {@link ChartCompositeProbeRecord}). The first four are the
|
|
8
|
+
outputs of the probe before 2.11.0: `two-sum` is TwoSum's low part (`s.l`), `two-product` Dekker's TwoProduct low part (`m.l`),
|
|
9
|
+
`double-word-add` the double-word sum's low part (`a.l`), `double-word-multiply` the Dekker double-word product (`q.h`, `q.l`).
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
export type ChartCompositeProbeComponent = "two-sum" | "two-product" | "double-word-add" | "double-word-multiply" | "fma-two-product" | "fma-double-word-multiply";
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## ChartCompositeProbeMismatch
|
|
16
|
+
|
|
17
|
+
One probe output that differs from its expected value: the component, the probe input's index, and the float32 bits (hex).
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
export interface ChartCompositeProbeMismatch {
|
|
21
|
+
component: ChartCompositeProbeComponent;
|
|
22
|
+
input: number;
|
|
23
|
+
got: string;
|
|
24
|
+
want: string;
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## ChartCompositeProbeRecord
|
|
29
|
+
|
|
30
|
+
The composite chart kernel's device probe (docs/WEBGPU.md, "Scene radiance on the GPU"): how the device evaluated the kernel's
|
|
31
|
+
double-float32 building blocks, and which product path the kernel was compiled with. Diagnostic; it never changes a result.
|
|
32
|
+
|
|
33
|
+
- `deviceClass`: `exact` (the written order, round to nearest); `contracted` (only the Dekker product paths differ, consistent
|
|
34
|
+
with a multiply and an add fused into one rounding); `reassociated` (a sum path differs and every differing sum low part is
|
|
35
|
+
zero, the value an algebraic simplification of (a + b) − a to b gives); `other` (anything else, such as a sum path that differs
|
|
36
|
+
with non-zero low parts, as a rounding not to nearest gives, or a non-finite output).
|
|
37
|
+
- `productPath`: `dekker` when the Dekker path passes, else `fma` when the fma path passes (which needs a fused `fma`), else null
|
|
38
|
+
(the device is refused for composite charts, the 2.3 elements and material-layers scenes).
|
|
39
|
+
- `fmaFused`: whether every fma TwoProduct low part was exact (a fused `fma`; WGSL also allows an unfused one).
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
export interface ChartCompositeProbeRecord {
|
|
43
|
+
deviceClass: "exact" | "contracted" | "reassociated" | "other";
|
|
44
|
+
productPath: "dekker" | "fma" | null;
|
|
45
|
+
fmaFused: boolean;
|
|
46
|
+
/** Probe inputs, each checked on every component. */
|
|
47
|
+
inputs: number;
|
|
48
|
+
/** Differing outputs per component. */
|
|
49
|
+
mismatchCounts: Readonly<Record<ChartCompositeProbeComponent, number>>;
|
|
50
|
+
/** The indices of the probe inputs (`PROBE_INPUTS`) whose output differs, per component. */
|
|
51
|
+
mismatchedInputs: Readonly<Record<ChartCompositeProbeComponent, readonly number[]>>;
|
|
52
|
+
/** The first differing outputs (at most eight), in component order. */
|
|
53
|
+
mismatches: readonly ChartCompositeProbeMismatch[];
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
5
57
|
## composeRelativeErrorBounds
|
|
6
58
|
|
|
7
59
|
Composes two `relative-to-reference` bounds through a pipeline `second ∘ first`, where the second
|
|
@@ -17,6 +69,20 @@ export function composeRelativeErrorBounds(first: ImageKernelRelativeErrorBound,
|
|
|
17
69
|
|
|
18
70
|
This call is synchronous; any supplied provider must follow its explicit synchronous contract.
|
|
19
71
|
|
|
72
|
+
## ImageKernelAdapterDescription
|
|
73
|
+
|
|
74
|
+
#481: the WebGPU adapter a device came from, as `GPUAdapter.info` describes it (W3C WebGPU, `GPUAdapterInfo`): each field
|
|
75
|
+
is the browser's string, or empty when the browser withholds it. Diagnostic only; it never changes a result.
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
export interface ImageKernelAdapterDescription {
|
|
79
|
+
vendor: string;
|
|
80
|
+
architecture: string;
|
|
81
|
+
device: string;
|
|
82
|
+
description: string;
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
20
86
|
## ImageKernelBackend
|
|
21
87
|
|
|
22
88
|
Requested or actual execution backend.
|
|
@@ -92,19 +158,20 @@ export class ImageKernelExecutionError extends Error {
|
|
|
92
158
|
|
|
93
159
|
## ImageKernelFailureReason
|
|
94
160
|
|
|
95
|
-
Failure classes reported by {@link ImageKernelExecutionError}.
|
|
161
|
+
Failure classes reported by {@link ImageKernelExecutionError}. `conformance-failed` (#481): a device failed the display view's
|
|
162
|
+
run-time self-check with `gpu: "require"`.
|
|
96
163
|
|
|
97
164
|
```ts
|
|
98
165
|
export type ImageKernelFailureReason = ImageKernelFallbackReason | "device-lost" | "out-of-memory" | "gpu-validation" |
|
|
99
|
-
"aborted" | "disposed" | "busy" | "unsupported-on-backend" | "unsupported-float32-domain" | "indeterminate-float32-classification";
|
|
166
|
+
"aborted" | "disposed" | "busy" | "unsupported-on-backend" | "unsupported-float32-domain" | "indeterminate-float32-classification" | "conformance-failed";
|
|
100
167
|
```
|
|
101
168
|
|
|
102
169
|
## ImageKernelFallbackReason
|
|
103
170
|
|
|
104
|
-
Why a requested
|
|
171
|
+
Why a requested `webgpu-f32` backend ran the CPU reference instead. `webgpu-disabled`: `setWebGpuEnabled(false)` in this realm.
|
|
105
172
|
|
|
106
173
|
```ts
|
|
107
|
-
export type ImageKernelFallbackReason = "webgpu-unavailable" | "adapter-unavailable" | "device-request-failed" |
|
|
174
|
+
export type ImageKernelFallbackReason = "webgpu-unavailable" | "webgpu-disabled" | "adapter-unavailable" | "device-request-failed" |
|
|
108
175
|
"insufficient-limits" | "unsupported-platform-endianness";
|
|
109
176
|
```
|
|
110
177
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# gpu/webgpu-switch.ts public contracts
|
|
2
|
+
|
|
3
|
+
The package and root API versions are recorded once in [Navigation](../API_REFERENCE.md) · [Developer guide](https://github.com/Photivra/photivra/blob/main/docs/DEVELOPERS.md). Generated signatures retain independent schema/model versions. Only the exports listed here are root-package contracts; module-local helpers are not supported deep imports.
|
|
4
|
+
|
|
5
|
+
## getWebGpuEnabled
|
|
6
|
+
|
|
7
|
+
Whether this realm may use WebGPU when a caller asks for it.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
export function getWebGpuEnabled(): boolean;
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
This call is synchronous; any supplied provider must follow its explicit synchronous contract.
|
|
14
|
+
|
|
15
|
+
## setWebGpuEnabled
|
|
16
|
+
|
|
17
|
+
Turns WebGPU on (`true`, the default) or off (`false`) for this realm. Anything but a boolean is refused.
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
export function setWebGpuEnabled(enabled: boolean): void;
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
This call is synchronous; any supplied provider must follow its explicit synchronous contract.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@photivra/engine",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.12.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Scientific TypeScript engine for camera optics, exposure, focus, motion, sensor sampling, diffraction, and digital imaging calculations.",
|
|
6
6
|
"type": "module",
|
|
@@ -88,6 +88,8 @@
|
|
|
88
88
|
"bench:webgpu": "vitest run --config vitest.webgpu-timing.config.ts",
|
|
89
89
|
"test:webgpu:hardware": "node scripts/run-webgpu-hardware.mjs test",
|
|
90
90
|
"bench:webgpu:hardware": "node scripts/run-webgpu-hardware.mjs bench",
|
|
91
|
+
"accept:gpu": "node scripts/accept-display-view-gpu.mjs --gpu",
|
|
92
|
+
"accept:gpu:hardware": "node scripts/accept-display-view-gpu.mjs --gpu --hardware",
|
|
91
93
|
"check:browser-surface": "node scripts/check-browser-surface.mjs",
|
|
92
94
|
"check:licenses": "node scripts/check-license-policy.mjs",
|
|
93
95
|
"check:license-headers": "node scripts/check-license-headers.mjs",
|