@photivra/engine 2.21.0 → 2.23.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.
Files changed (172) hide show
  1. package/CHANGELOG.md +150 -1
  2. package/CITATION.cff +1 -1
  3. package/README.md +6 -6
  4. package/SECURITY.md +1 -1
  5. package/THIRD_PARTY.md +11 -0
  6. package/dist/capture/c2pa-embed.d.ts +116 -0
  7. package/dist/capture/c2pa-embed.js +493 -0
  8. package/dist/capture/c2pa-embed.js.map +1 -0
  9. package/dist/capture/dng-import.d.ts +73 -8
  10. package/dist/capture/dng-import.js +315 -80
  11. package/dist/capture/dng-import.js.map +1 -1
  12. package/dist/capture/dng-opcodes.d.ts +96 -0
  13. package/dist/capture/dng-opcodes.js +391 -0
  14. package/dist/capture/dng-opcodes.js.map +1 -0
  15. package/dist/capture/dng-profile-maps.d.ts +99 -0
  16. package/dist/capture/dng-profile-maps.js +381 -0
  17. package/dist/capture/dng-profile-maps.js.map +1 -0
  18. package/dist/capture/dng-stage-image.d.ts +23 -0
  19. package/dist/capture/dng-stage-image.js +65 -0
  20. package/dist/capture/dng-stage-image.js.map +1 -0
  21. package/dist/capture/jpeg-xl-tiles.d.ts +22 -0
  22. package/dist/capture/jpeg-xl-tiles.js +151 -0
  23. package/dist/capture/jpeg-xl-tiles.js.map +1 -0
  24. package/dist/capture/lossy-jpeg.d.ts +17 -0
  25. package/dist/capture/lossy-jpeg.js +369 -0
  26. package/dist/capture/lossy-jpeg.js.map +1 -0
  27. package/dist/capture/native-raw-development.d.ts +2 -1
  28. package/dist/capture/native-raw-development.js.map +1 -1
  29. package/dist/color/neighbor-highlight-reconstruction.d.ts +76 -0
  30. package/dist/color/neighbor-highlight-reconstruction.js +257 -0
  31. package/dist/color/neighbor-highlight-reconstruction.js.map +1 -0
  32. package/dist/color/sensor-color-development.d.ts +5 -0
  33. package/dist/color/sensor-color-development.js +7 -1
  34. package/dist/color/sensor-color-development.js.map +1 -1
  35. package/dist/color/spectral-spikiness.d.ts +11 -0
  36. package/dist/color/spectral-spikiness.js +23 -0
  37. package/dist/color/spectral-spikiness.js.map +1 -0
  38. package/dist/core/execution-error.d.ts +21 -0
  39. package/dist/core/execution-error.js +12 -0
  40. package/dist/core/execution-error.js.map +1 -0
  41. package/dist/core/version.d.ts +1 -1
  42. package/dist/core/version.js +1 -1
  43. package/dist/core/version.js.map +1 -1
  44. package/dist/facade/catalogue-lens-signal.d.ts +26 -1
  45. package/dist/facade/catalogue-lens-signal.js +25 -7
  46. package/dist/facade/catalogue-lens-signal.js.map +1 -1
  47. package/dist/facade/diffraction-provider.d.ts +1 -1
  48. package/dist/facade/diffraction-provider.js +4 -4
  49. package/dist/facade/diffraction-provider.js.map +1 -1
  50. package/dist/facade/display-view-gpu-session.js +38 -6
  51. package/dist/facade/display-view-gpu-session.js.map +1 -1
  52. package/dist/facade/display-view-gpu.d.ts +13 -5
  53. package/dist/facade/display-view-gpu.js.map +1 -1
  54. package/dist/facade/display-view-normal.d.ts +15 -0
  55. package/dist/facade/display-view-normal.js +44 -0
  56. package/dist/facade/display-view-normal.js.map +1 -0
  57. package/dist/facade/display-view-rendering.d.ts +102 -0
  58. package/dist/facade/display-view-rendering.js +633 -0
  59. package/dist/facade/display-view-rendering.js.map +1 -0
  60. package/dist/facade/display-view.d.ts +37 -65
  61. package/dist/facade/display-view.js +147 -476
  62. package/dist/facade/display-view.js.map +1 -1
  63. package/dist/facade/expected-signal-setup.js +2 -2
  64. package/dist/facade/expected-signal-setup.js.map +1 -1
  65. package/dist/facade/fast-methods.d.ts +1 -1
  66. package/dist/facade/fast-methods.js +37 -8
  67. package/dist/facade/fast-methods.js.map +1 -1
  68. package/dist/facade/generic-lens-capture.d.ts +1 -1
  69. package/dist/facade/generic-lens-capture.js +1 -1
  70. package/dist/facade/generic-lens-capture.js.map +1 -1
  71. package/dist/facade/image-plane.js +41 -10
  72. package/dist/facade/image-plane.js.map +1 -1
  73. package/dist/facade/on-demand-kits.d.ts +14 -0
  74. package/dist/facade/on-demand-kits.js +36 -0
  75. package/dist/facade/on-demand-kits.js.map +1 -0
  76. package/dist/facade/opt-in-kit.d.ts +9 -0
  77. package/dist/facade/opt-in-kit.js +11 -0
  78. package/dist/facade/opt-in-kit.js.map +1 -0
  79. package/dist/facade/quality-kit.d.ts +21 -0
  80. package/dist/facade/quality-kit.js +23 -0
  81. package/dist/facade/quality-kit.js.map +1 -0
  82. package/dist/facade/quality-paths.d.ts +22 -0
  83. package/dist/facade/quality-paths.js +44 -0
  84. package/dist/facade/quality-paths.js.map +1 -0
  85. package/dist/facade/scene-radiance.d.ts +18 -2
  86. package/dist/facade/scene-radiance.js +6 -4
  87. package/dist/facade/scene-radiance.js.map +1 -1
  88. package/dist/facade/simulate-capture.d.ts +32 -13
  89. package/dist/facade/simulate-capture.js +162 -69
  90. package/dist/facade/simulate-capture.js.map +1 -1
  91. package/dist/facade/simulate-display-view.d.ts +10 -12
  92. package/dist/facade/simulate-display-view.js +57 -48
  93. package/dist/facade/simulate-display-view.js.map +1 -1
  94. package/dist/gpu/display-view-gpu-renderer.d.ts +43 -0
  95. package/dist/gpu/display-view-gpu-renderer.js +134 -0
  96. package/dist/gpu/display-view-gpu-renderer.js.map +1 -0
  97. package/dist/gpu/display-view-image-material-module.d.ts +3 -2
  98. package/dist/gpu/display-view-image-material-module.js +25 -3
  99. package/dist/gpu/display-view-image-material-module.js.map +1 -1
  100. package/dist/gpu/display-view-image-quality.d.ts +43 -1
  101. package/dist/gpu/display-view-image-quality.js +256 -11
  102. package/dist/gpu/display-view-image-quality.js.map +1 -1
  103. package/dist/gpu/display-view-quality-gpu.d.ts +13 -64
  104. package/dist/gpu/display-view-quality-gpu.js +55 -240
  105. package/dist/gpu/display-view-quality-gpu.js.map +1 -1
  106. package/dist/gpu/display-view-speed-gpu.d.ts +16 -16
  107. package/dist/gpu/display-view-speed-gpu.js +62 -19
  108. package/dist/gpu/display-view-speed-gpu.js.map +1 -1
  109. package/dist/gpu/image-kernel-accelerator.js +3 -0
  110. package/dist/gpu/image-kernel-accelerator.js.map +1 -1
  111. package/dist/gpu/image-kernel-execution.d.ts +2 -13
  112. package/dist/gpu/image-kernel-execution.js +2 -10
  113. package/dist/gpu/image-kernel-execution.js.map +1 -1
  114. package/dist/gpu/wgsl-display-view-coupled-stub.d.ts +13 -0
  115. package/dist/gpu/wgsl-display-view-coupled-stub.js +29 -0
  116. package/dist/gpu/wgsl-display-view-coupled-stub.js.map +1 -0
  117. package/dist/gpu/wgsl-display-view-coupled.d.ts +91 -0
  118. package/dist/gpu/wgsl-display-view-coupled.js +365 -0
  119. package/dist/gpu/wgsl-display-view-coupled.js.map +1 -0
  120. package/dist/gpu/wgsl-display-view-neighbors.d.ts +46 -0
  121. package/dist/gpu/wgsl-display-view-neighbors.js +114 -0
  122. package/dist/gpu/wgsl-display-view-neighbors.js.map +1 -0
  123. package/dist/gpu/wgsl-display-view-quality-kernel.d.ts +6 -9
  124. package/dist/gpu/wgsl-display-view-quality-kernel.js +113 -113
  125. package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -1
  126. package/dist/gpu/wgsl-display-view-speed-kernel.d.ts +1 -41
  127. package/dist/gpu/wgsl-display-view-speed-kernel.js +73 -10
  128. package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -1
  129. package/dist/index.d.ts +11 -3
  130. package/dist/index.js +9 -1
  131. package/dist/index.js.map +1 -1
  132. package/dist/output/camera-channel-response.d.ts +50 -0
  133. package/dist/output/camera-channel-response.js +69 -0
  134. package/dist/output/camera-channel-response.js.map +1 -0
  135. package/dist/output/native-capture-sdr.js +5 -2
  136. package/dist/output/native-capture-sdr.js.map +1 -1
  137. package/dist/output/sdr-rendering.d.ts +18 -1
  138. package/dist/output/sdr-rendering.js +39 -2
  139. package/dist/output/sdr-rendering.js.map +1 -1
  140. package/dist/sensor/native-sensor-report.d.ts +10 -0
  141. package/dist/sensor/native-sensor-report.js +16 -0
  142. package/dist/sensor/native-sensor-report.js.map +1 -0
  143. package/dist/sensor/sensor-characteristics.d.ts +81 -13
  144. package/dist/sensor/sensor-characteristics.js +10 -6
  145. package/dist/sensor/sensor-characteristics.js.map +1 -1
  146. package/docs/API_REFERENCE.md +117 -4
  147. package/docs/QUICK_START.md +37 -8
  148. package/docs/USAGE.md +105 -22
  149. package/docs/api/capture-c2pa-embed.md +177 -0
  150. package/docs/api/capture-dng-import.md +86 -10
  151. package/docs/api/capture-dng-opcodes.md +93 -0
  152. package/docs/api/capture-dng-profile-maps.md +141 -0
  153. package/docs/api/capture-dng-stage-image.md +43 -0
  154. package/docs/api/capture-jpeg-xl-tiles.md +33 -0
  155. package/docs/api/capture-lossy-jpeg.md +41 -0
  156. package/docs/api/capture-native-raw-development.md +2 -1
  157. package/docs/api/core-execution-error.md +43 -0
  158. package/docs/api/core-version.md +1 -1
  159. package/docs/api/exports.json +255 -5
  160. package/docs/api/facade-display-view-gpu.md +5 -2
  161. package/docs/api/facade-display-view.md +11 -15
  162. package/docs/api/facade-fast-methods.md +38 -9
  163. package/docs/api/facade-quality-paths.md +24 -0
  164. package/docs/api/facade-scene-radiance.md +1 -1
  165. package/docs/api/facade-simulate-capture.md +24 -7
  166. package/docs/api/facade-simulate-display-view.md +10 -12
  167. package/docs/api/gpu-image-kernel-execution.md +0 -36
  168. package/docs/api/output-camera-channel-response.md +55 -0
  169. package/docs/api/output-sdr-rendering.md +6 -1
  170. package/docs/api/sensor-sensor-characteristics.md +54 -2
  171. package/llms.txt +1 -0
  172. package/package.json +6 -5
@@ -16,7 +16,9 @@
16
16
  * (`insufficient-limits` thrown by `render`: #492, a large defocus kernel's table on a scene of many materials);
17
17
  * - before the first GPU render on the device a short conformance self-check runs once (single-flight): the built-in cases run
18
18
  * the existing `webgpu-f32` convolution kernel against the float64 reference within its a-priori bound, then the renderer's own
19
- * cases; a failure keeps the whole view on the CPU, labelled `conformance-failed`, with the adapter recorded;
19
+ * cases; a failure keeps the whole view on the CPU, labelled `conformance-failed`, with the adapter recorded; #594: cases of
20
+ * code the renderer loads on demand (the Quality kernels) run once, before the first render that needs them, and a failure
21
+ * there keeps that render and every later one on the CPU;
20
22
  * - GPU renders of one session run one at a time on the device (the accelerator's single flight; later renders wait);
21
23
  * - a lost device falls back to the CPU for that render and every later one, labelled `device-lost`; `dispose()` releases an
22
24
  * owned device, and later renders run on the CPU labelled `disposed`.
@@ -27,7 +29,7 @@ import { acquireWebGpuRuntime } from "../gpu/webgpu-runtime.js";
27
29
  import { ImageKernelExecutionError, WEBGPU_F32_LIMITATIONS } from "../gpu/image-kernel-execution.js";
28
30
  import { acceleratorRuntime, convolveIrradianceOnRuntime } from "../gpu/image-kernel-accelerator.js";
29
31
  import { calculateIrradianceConvolutionPlan, convolveIrradianceRows } from "../optics/irradiance-convolution.js";
30
- import { displayViewGpuRendererFactory as engineDisplayViewGpuRendererFactory } from "../gpu/display-view-quality-gpu.js";
32
+ import { displayViewGpuRendererFactory as engineDisplayViewGpuRendererFactory } from "../gpu/display-view-gpu-renderer.js";
31
33
  import { cpuDisplayViewExecution, displayViewGpuRendererFactory, setDisplayViewGpuRendererFactory } from "./display-view-gpu.js";
32
34
  // #478, #479: the engine's own renderer, the display view's Speed and Quality kernels behind one renderer
33
35
  // (`src/gpu/display-view-quality-gpu.ts`), is registered when this module loads (that is, when a prepared view first asks for the
@@ -80,7 +82,8 @@ export async function openDisplayViewGpuSession(options, request, signal) {
80
82
  if (request.lens)
81
83
  return fallBack(options, "unsupported-on-backend", "the GPU display-view renderers do not render lens.projection, lens.distortion, lens.vignetting or " +
82
84
  "camera rotation (#563); the CPU reference renders them. No device was requested.");
83
- if (request.mixedIllumination)
85
+ // #597: an image-plane print under mixed light renders on the device (its Quality passes light each lattice point); charts keep the CPU.
86
+ if (request.mixedIllumination && request.scene !== "image-plane")
84
87
  return fallBack(options, "unsupported-on-backend", "the GPU renderers light chart materials with one illuminant; the CPU reference renders mixed illumination (#550). No device was requested.");
85
88
  let runtime, owned = false;
86
89
  if (isAccelerator(options.gpuDevice)) {
@@ -179,8 +182,12 @@ export const DISPLAY_VIEW_GPU_BUILT_IN_CASES = Object.freeze([
179
182
  convolutionCase("image-kernel:convolution:16x12-r1", 16, 12, 1, 16, 12, 481),
180
183
  convolutionCase("image-kernel:convolution:32x24-r3-patches", 32, 24, 3, 16, 12, 4781)
181
184
  ]);
182
- async function runConformance(runtime, renderer, signal) {
183
- const cases = [...DISPLAY_VIEW_GPU_BUILT_IN_CASES, ...(renderer.conformanceCases ?? [])], ids = Object.freeze(cases.map((c) => c.id));
185
+ /**
186
+ * Runs `cases` in order and returns the record. `before` is a record that already passed (#594: the cases run at the device's
187
+ * first render, when `cases` are a renderer's on-demand cases); its ids come first in the record.
188
+ */
189
+ async function runConformance(runtime, cases, signal, before = null) {
190
+ const ids = Object.freeze([...(before?.cases ?? []), ...cases.map((c) => c.id)]);
184
191
  for (const c of cases) {
185
192
  let outcome;
186
193
  try {
@@ -198,6 +205,10 @@ async function runConformance(runtime, renderer, signal) {
198
205
  return Object.freeze({ cases: ids, passed: true, failedCase: null, detail: null });
199
206
  }
200
207
  // ---------------------------------------------------------------------------------------------------------------
208
+ /** #594: the error of on-demand renderer code that could not be loaded. */
209
+ function qualityCodeUnavailable(error) {
210
+ return error instanceof ImageKernelExecutionError && error.reason === "quality-code-unavailable";
211
+ }
201
212
  function createSession(options, runtime, owned, renderer) {
202
213
  const adapter = runtime.adapter;
203
214
  let disposed = false, lost = false, conformance = null, checking = null;
@@ -214,10 +225,24 @@ function createSession(options, runtime, owned, renderer) {
214
225
  if (conformance)
215
226
  return Promise.resolve(conformance);
216
227
  if (!checking) {
217
- checking = runConformance(runtime, renderer, signal).then((result) => { conformance = result; return result; }, (error) => { checking = null; throw error; });
228
+ checking = runConformance(runtime, [...DISPLAY_VIEW_GPU_BUILT_IN_CASES, ...(renderer.conformanceCases ?? [])], signal).then((result) => { conformance = result; return result; }, (error) => { checking = null; throw error; });
218
229
  }
219
230
  return checking;
220
231
  }
232
+ /**
233
+ * #594: the renderer's on-demand cases for a render (the Quality kernels' self-check, owner decision 2026-11-10), run once
234
+ * after the device's own check passed (single flight); the record then lists both and replaces the session's record, so a
235
+ * failure keeps this render and every later one on the CPU, as a failure at the first render does.
236
+ */
237
+ let onDemand = null;
238
+ function onDemandCheck(setup, passed, signal) {
239
+ if (onDemand)
240
+ return onDemand;
241
+ const cases = renderer.onDemandConformanceCases?.(setup);
242
+ if (!cases)
243
+ return Promise.resolve(passed);
244
+ return onDemand = cases.then((list) => runConformance(runtime, list, signal, passed)).then((result) => conformance = result, (error) => { onDemand = null; throw error; });
245
+ }
221
246
  function lostError(error) { return (error instanceof ImageKernelExecutionError && error.reason === "device-lost") || runtime.isLost(); }
222
247
  return {
223
248
  async render(setup, signal, cpu) {
@@ -230,12 +255,17 @@ function createSession(options, runtime, owned, renderer) {
230
255
  let check;
231
256
  try {
232
257
  check = await selfCheck(signal);
258
+ if (check.passed)
259
+ check = await onDemandCheck(setup, check, signal);
233
260
  }
234
261
  catch (error) {
235
262
  if (lostError(error)) {
236
263
  lost = true;
237
264
  return fallback("device-lost", "the WebGPU device was lost during its conformance check.", cpu);
238
265
  }
266
+ // #594: the on-demand code did not load: this render runs the CPU reference; the next one that needs it tries again.
267
+ if (qualityCodeUnavailable(error))
268
+ return fallback("quality-code-unavailable", error.message, cpu);
239
269
  setup.checkAbort();
240
270
  throw error;
241
271
  }
@@ -258,6 +288,8 @@ function createSession(options, runtime, owned, renderer) {
258
288
  return fallback("device-lost", "the WebGPU device was lost during a render; the rest of the view runs on the CPU.", cpu);
259
289
  }
260
290
  setup.checkAbort();
291
+ if (qualityCodeUnavailable(error))
292
+ return fallback("quality-code-unavailable", error.message, cpu);
261
293
  if (error instanceof ImageKernelExecutionError && error.reason === "unsupported-on-backend")
262
294
  return fallback("unsupported-on-backend", "the GPU display-view renderer \"" + renderer.id + "\" does not cover this render: " + error.message, cpu, probeOf(error));
263
295
  // #492: a render past the device's limits (a kernel table or band above its storage binding limit) runs the CPU reference too.
@@ -1 +1 @@
1
- {"version":3,"file":"display-view-gpu-session.js","sourceRoot":"","sources":["../../src/facade/display-view-gpu-session.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * #481: the device handling behind `prepareDisplayView(request, { gpu: \"auto\" | \"require\", gpuDevice })`. Loaded on demand by\n * `simulate-display-view.ts`, so the GPU code stays out of bundles that never ask for it. One session per prepared view:\n *\n * - the realm's switch (`setWebGpuEnabled(false)`) vetoes before anything else: `\"auto\"` falls back with `webgpu-disabled`,\n * `\"require\"` throws it;\n * - with no renderer registered (the engine registers its renderer, the Speed and Quality kernels of #478 and #479, when this module\n * loads; a caller may replace it or set null) no device is requested: `unsupported-on-backend`;\n * - the device is the handle's (`gpuDevice`: an `ImageKernelAccelerator`'s device, shared and left to its owner, or a WebGPU\n * entry point to acquire from), or acquired from `navigator.gpu` and owned by the session; the accelerator's acquisition\n * reasons apply, and the request's `signal` aborts the acquisition;\n * - the renderer must support the request, else `unsupported-on-backend`; a render the renderer refuses only when rendering\n * (`unsupported-on-backend` thrown by `render`: a coarse view, a device that fails the composite chart probe, #491) runs the\n * CPU reference for that render with the same label, and so does a render whose tables or bands exceed the device's limits\n * (`insufficient-limits` thrown by `render`: #492, a large defocus kernel's table on a scene of many materials);\n * - before the first GPU render on the device a short conformance self-check runs once (single-flight): the built-in cases run\n * the existing `webgpu-f32` convolution kernel against the float64 reference within its a-priori bound, then the renderer's own\n * cases; a failure keeps the whole view on the CPU, labelled `conformance-failed`, with the adapter recorded;\n * - GPU renders of one session run one at a time on the device (the accelerator's single flight; later renders wait);\n * - a lost device falls back to the CPU for that render and every later one, labelled `device-lost`; `dispose()` releases an\n * owned device, and later renders run on the CPU labelled `disposed`.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { getWebGpuEnabled } from \"../gpu/webgpu-switch.js\";\nimport { acquireWebGpuRuntime, type WebGpuRuntime } from \"../gpu/webgpu-runtime.js\";\nimport { ImageKernelExecutionError, WEBGPU_F32_LIMITATIONS, type ChartCompositeProbeRecord, type ImageKernelAdapterDescription } from \"../gpu/image-kernel-execution.js\";\nimport { acceleratorRuntime, convolveIrradianceOnRuntime } from \"../gpu/image-kernel-accelerator.js\";\nimport { calculateIrradianceConvolutionPlan, convolveIrradianceRows, type IrradianceConvolutionInput } from \"../optics/irradiance-convolution.js\";\nimport type { DisplayViewRenderResult, DisplayViewSetup } from \"./display-view.js\";\nimport { displayViewGpuRendererFactory as engineDisplayViewGpuRendererFactory } from \"../gpu/display-view-quality-gpu.js\";\nimport { cpuDisplayViewExecution, displayViewGpuRendererFactory, setDisplayViewGpuRendererFactory, type DisplayViewExecution, type DisplayViewGpuConformance, type DisplayViewGpuConformanceCase,\n type DisplayViewGpuFallbackReason, type DisplayViewGpuRenderer, type DisplayViewGpuRequest, type ParsedPrepareDisplayViewOptions } from \"./display-view-gpu.js\";\n\n// #478, #479: the engine's own renderer, the display view's Speed and Quality kernels behind one renderer\n// (`src/gpu/display-view-quality-gpu.ts`), is registered when this module loads (that is, when a prepared view first asks for the\n// GPU) unless a caller registered a renderer before; a test that needs \"no renderer\" sets the factory to null.\nif (displayViewGpuRendererFactory() === null) setDisplayViewGpuRendererFactory(engineDisplayViewGpuRendererFactory);\n\n/** Internal: the GPU side of one prepared view. */\nexport interface DisplayViewGpuSession {\n /** Renders `setup` on the GPU when the session can, else through `cpu`; the label says which ran. */\n render(setup: DisplayViewSetup, signal: AbortSignal | undefined, cpu: () => Promise<DisplayViewRenderResult>): Promise<{ rendered: DisplayViewRenderResult; execution: DisplayViewExecution }>;\n dispose(): void;\n}\n\n/** A session that renders every view on the CPU with one fixed reason. */\nfunction cpuSession(options: ParsedPrepareDisplayViewOptions, reason: DisplayViewGpuFallbackReason, detail: string, adapter: ImageKernelAdapterDescription | null,\n conformance: DisplayViewGpuConformance | null): DisplayViewGpuSession {\n const execution = cpuDisplayViewExecution(options.gpu, reason, adapter, conformance, detail);\n return { async render(_setup, _signal, cpu): Promise<{ rendered: DisplayViewRenderResult; execution: DisplayViewExecution }> { return { rendered: await cpu(), execution }; },\n dispose(): void { /* nothing acquired */ } };\n}\n\n/** `\"require\"` throws the reason; `\"auto\"` gets a CPU session labelled with it. */\nfunction fallBack(options: ParsedPrepareDisplayViewOptions, reason: DisplayViewGpuFallbackReason, detail: string, adapter: ImageKernelAdapterDescription | null = null,\n conformance: DisplayViewGpuConformance | null = null): DisplayViewGpuSession {\n if (options.gpu === \"require\") throw requireError(reason, detail);\n return cpuSession(options, reason, detail, adapter, conformance);\n}\n/**\n * The error `\"require\"` throws instead of falling back. Every display-view fallback reason is also a failure reason of the accelerator's\n * error. A refusal by the composite chart probe carries its record as `probe` (the structured detail of the message).\n */\nfunction requireError(reason: DisplayViewGpuFallbackReason, detail: string, probe: ChartCompositeProbeRecord | null = null): ImageKernelExecutionError {\n const error = new ImageKernelExecutionError(reason, \"prepareDisplayView with gpu \\\"require\\\": \" + detail);\n if (probe) Object.defineProperty(error, \"probe\", { value: probe, enumerable: true });\n return error;\n}\n/** The composite chart probe's record on a refusal (`ChartCompositeProbeError.probe`), or null. */\nfunction probeOf(error: unknown): ChartCompositeProbeRecord | null {\n const probe = (error as { probe?: unknown }).probe;\n return typeof probe === \"object\" && probe !== null ? probe as ChartCompositeProbeRecord : null;\n}\n\n/** True for an object shaped like an `ImageKernelAccelerator` (the handle form that shares a device). */\nfunction isAccelerator(value: unknown): boolean {\n return typeof value === \"object\" && value !== null && typeof (value as { convolveIrradiance?: unknown }).convolveIrradiance === \"function\" &&\n typeof (value as { backend?: unknown }).backend === \"string\";\n}\n\n/**\n * Internal (#481): opens the GPU session of a prepared view, or throws (`\"require\"`) when the GPU cannot be used. Called only\n * for `gpu: \"auto\" | \"require\"`.\n */\nexport async function openDisplayViewGpuSession(options: ParsedPrepareDisplayViewOptions, request: DisplayViewGpuRequest, signal: AbortSignal | undefined): Promise<DisplayViewGpuSession> {\n if (!getWebGpuEnabled()) return fallBack(options, \"webgpu-disabled\", \"WebGPU is switched off in this realm (setWebGpuEnabled(false)).\");\n const factory = displayViewGpuRendererFactory();\n if (!factory) return fallBack(options, \"unsupported-on-backend\", \"this version of the engine has no GPU display-view renderer (#478); no device was requested.\");\n // #563: the lens signal (projection, distortion, vignetting, rotation) runs on the CPU reference only; no device is requested for it.\n if (request.lens) return fallBack(options, \"unsupported-on-backend\", \"the GPU display-view renderers do not render lens.projection, lens.distortion, lens.vignetting or \" +\n \"camera rotation (#563); the CPU reference renders them. No device was requested.\");\n if (request.mixedIllumination) return fallBack(options, \"unsupported-on-backend\", \"the GPU renderers light chart materials with one illuminant; the CPU reference renders mixed illumination (#550). No device was requested.\");\n let runtime: WebGpuRuntime, owned = false;\n if (isAccelerator(options.gpuDevice)) {\n const shared = acceleratorRuntime(options.gpuDevice) as WebGpuRuntime | null | undefined;\n if (shared === undefined) throw new InvalidConfigurationError(\"prepareDisplayView options.gpuDevice must be an accelerator created by createImageKernelAccelerator.\");\n const accelerator = options.gpuDevice as { state: string; fallbackReason: DisplayViewGpuFallbackReason | null };\n if (accelerator.state === \"disposed\") throw new InvalidConfigurationError(\"prepareDisplayView options.gpuDevice is a disposed accelerator.\");\n if (shared === null) return fallBack(options, accelerator.fallbackReason ?? \"webgpu-unavailable\", \"the given accelerator runs the CPU reference and has no device.\");\n if (shared.isLost()) return fallBack(options, \"device-lost\", \"the given accelerator's device was lost.\", shared.adapter);\n runtime = shared;\n } else {\n const gpu = options.gpuDevice !== undefined ? options.gpuDevice : (globalThis as { navigator?: { gpu?: unknown } }).navigator?.gpu;\n let acquired: Awaited<ReturnType<typeof acquireWebGpuRuntime>>;\n try { acquired = await acquireWebGpuRuntime(gpu, undefined, signal); }\n catch (error) {\n if (error instanceof ImageKernelExecutionError && error.reason === \"aborted\") throw new InvalidConfigurationError(\"prepareDisplayView aborted.\");\n throw error;\n }\n if (\"failure\" in acquired) return fallBack(options, acquired.failure, acquired.message);\n runtime = acquired.runtime; owned = true;\n }\n const renderer = factory(runtime), supported = renderer.supports(request);\n if (supported !== true) {\n if (owned) runtime.destroy();\n return fallBack(options, \"unsupported-on-backend\", \"the GPU display-view renderer \\\"\" + renderer.id + \"\\\" does not support this request: \" + supported, runtime.adapter);\n }\n return createSession(options, runtime, owned, renderer);\n}\n\n// ---------------------------------------------------------------------------------------------------------------\n// Run-time conformance self-check.\n\n/** A fixed, seeded test image (mulberry32) for the built-in cases. */\nfunction seededSamples(count: number, seed: number): Float64Array {\n let a = seed >>> 0;\n const out = new Float64Array(count);\n for (let i = 0; i < count; i++) {\n a = (a + 0x6d2b79f5) >>> 0;\n let t = Math.imul(a ^ (a >>> 15), 1 | a);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n const u = ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n out[i] = u < 0.05 ? 0 : 10 ** (u * 6 - 3);\n }\n return out;\n}\n/** One convolution case: normalized Gaussian kernels of width `sigma` per patch, compared with the float64 reference within the a-priori bound. */\nfunction convolutionCase(id: string, width: number, height: number, radius: number, patchWidth: number, patchHeight: number, seed: number): DisplayViewGpuConformanceCase {\n return { id, async run(runtime, signal): Promise<true | string> {\n const size = 2 * radius + 1, taps = size * size, columns = Math.ceil(width / patchWidth), rows = Math.ceil(height / patchHeight);\n const kernels = new Float64Array(columns * rows * taps);\n for (let p = 0; p < columns * rows; p++) {\n const sigma = 0.6 + 0.4 * (p % 3), scale = 0.8 + 0.05 * p;\n let sum = 0;\n for (let v = -radius; v <= radius; v++) for (let u = -radius; u <= radius; u++) { const w = Math.exp(-0.5 * (u * u + v * v) / (sigma * sigma)); kernels[p * taps + (v + radius) * size + u + radius] = w; sum += w; }\n for (let t = 0; t < taps; t++) kernels[p * taps + t] = kernels[p * taps + t]! / sum * Math.min(1, scale);\n }\n const input: IrradianceConvolutionInput = { schemaVersion: \"0.1.0\", width, height, kernelRadius: radius, patchWidth, patchHeight, boundary: \"zero-outside-grid\",\n samples: seededSamples(width * height, seed), kernels };\n const plan = calculateIrradianceConvolutionPlan(input), reference = new Float64Array(width * height);\n convolveIrradianceRows(plan, input.samples, input.kernels, 0, height, reference);\n {\n const result = await convolveIrradianceOnRuntime(runtime, input, signal);\n const bound = result.execution.errorBound;\n if (!bound || bound.kind !== \"relative-to-reference\") return \"the convolution reported no relative bound.\";\n let worst = 0, worstIndex = -1;\n for (let i = 0; i < reference.length; i++) {\n const allowed = bound.relative * reference[i]! + bound.absolute, excess = Math.abs(result.values[i]! - reference[i]!) - allowed;\n if (excess > worst) { worst = excess; worstIndex = i; }\n }\n return worstIndex < 0 ? true : \"sample \" + worstIndex + \" differs from the reference by \" + Math.abs(result.values[worstIndex]! - reference[worstIndex]!) +\n \", more than the a-priori bound \" + (bound.relative * reference[worstIndex]! + bound.absolute) + \".\";\n }\n } };\n}\n/** The built-in cases, run on every device before its first display-view render: the existing convolution kernel on two small images. */\nexport const DISPLAY_VIEW_GPU_BUILT_IN_CASES: readonly DisplayViewGpuConformanceCase[] = Object.freeze([\n convolutionCase(\"image-kernel:convolution:16x12-r1\", 16, 12, 1, 16, 12, 481),\n convolutionCase(\"image-kernel:convolution:32x24-r3-patches\", 32, 24, 3, 16, 12, 4781)\n]);\n\nasync function runConformance(runtime: WebGpuRuntime, renderer: DisplayViewGpuRenderer, signal: AbortSignal | undefined): Promise<DisplayViewGpuConformance> {\n const cases = [...DISPLAY_VIEW_GPU_BUILT_IN_CASES, ...(renderer.conformanceCases ?? [])], ids = Object.freeze(cases.map((c) => c.id));\n for (const c of cases) {\n let outcome: true | string;\n try { outcome = await c.run(runtime, signal); }\n catch (error) {\n // An abort is the caller's, not the device's; everything else the device did wrong is a failed case.\n if (error instanceof ImageKernelExecutionError && error.reason === \"aborted\") throw error;\n outcome = \"the case threw \" + (error instanceof ImageKernelExecutionError ? error.reason + \": \" : \"\") + (error instanceof Error ? error.message : String(error));\n }\n if (outcome !== true) return Object.freeze({ cases: ids, passed: false, failedCase: c.id, detail: outcome });\n }\n return Object.freeze({ cases: ids, passed: true, failedCase: null, detail: null });\n}\n\n// ---------------------------------------------------------------------------------------------------------------\n\nfunction createSession(options: ParsedPrepareDisplayViewOptions, runtime: WebGpuRuntime, owned: boolean, renderer: DisplayViewGpuRenderer): DisplayViewGpuSession {\n const adapter = runtime.adapter;\n let disposed = false, lost = false, conformance: DisplayViewGpuConformance | null = null, checking: Promise<DisplayViewGpuConformance> | null = null;\n /** The last GPU turn: renders queue behind it, so one dispatch runs at a time on the device. */\n let tail: Promise<unknown> = Promise.resolve();\n /** A CPU fallback label for `\"auto\"`; with `\"require\"` the same event is an error. */\n const fallback = async (reason: DisplayViewGpuFallbackReason, detail: string, cpu: () => Promise<DisplayViewRenderResult>, compositeProbe: ChartCompositeProbeRecord | null = null):\n Promise<{ rendered: DisplayViewRenderResult; execution: DisplayViewExecution }> => {\n if (options.gpu === \"require\") throw requireError(reason, detail, compositeProbe);\n return { rendered: await cpu(), execution: cpuDisplayViewExecution(options.gpu, reason, adapter, conformance, detail, compositeProbe) };\n };\n /** The self-check, run once per session (single flight); a failing check is remembered and never repeated. */\n function selfCheck(signal: AbortSignal | undefined): Promise<DisplayViewGpuConformance> {\n if (conformance) return Promise.resolve(conformance);\n if (!checking) {\n checking = runConformance(runtime, renderer, signal).then((result) => { conformance = result; return result; }, (error: unknown) => { checking = null; throw error; });\n }\n return checking;\n }\n function lostError(error: unknown): boolean { return (error instanceof ImageKernelExecutionError && error.reason === \"device-lost\") || runtime.isLost(); }\n return {\n async render(setup, signal, cpu): Promise<{ rendered: DisplayViewRenderResult; execution: DisplayViewExecution }> {\n if (disposed) return fallback(\"disposed\", \"the prepared view was disposed.\", cpu);\n if (lost || runtime.isLost()) { lost = true; return fallback(\"device-lost\", \"the WebGPU device was lost; the rest of the view runs on the CPU.\", cpu); }\n let check: DisplayViewGpuConformance;\n try { check = await selfCheck(signal); }\n catch (error) {\n if (lostError(error)) { lost = true; return fallback(\"device-lost\", \"the WebGPU device was lost during its conformance check.\", cpu); }\n setup.checkAbort();\n throw error;\n }\n if (!check.passed) return fallback(\"conformance-failed\", \"the device failed conformance case \\\"\" + check.failedCase + \"\\\": \" + check.detail, cpu);\n const turn = tail.then(async () => {\n if (disposed || lost || runtime.isLost()) return null;\n setup.checkAbort();\n return renderer.render({ setup, signal });\n });\n tail = turn.catch(() => undefined);\n let output: Awaited<typeof turn>;\n try { output = await turn; }\n catch (error) {\n if (lostError(error)) { lost = true; return fallback(\"device-lost\", \"the WebGPU device was lost during a render; the rest of the view runs on the CPU.\", cpu); }\n setup.checkAbort();\n if (error instanceof ImageKernelExecutionError && error.reason === \"unsupported-on-backend\")\n return fallback(\"unsupported-on-backend\", \"the GPU display-view renderer \\\"\" + renderer.id + \"\\\" does not cover this render: \" + error.message, cpu, probeOf(error));\n // #492: a render past the device's limits (a kernel table or band above its storage binding limit) runs the CPU reference too.\n if (error instanceof ImageKernelExecutionError && error.reason === \"insufficient-limits\")\n return fallback(\"insufficient-limits\", \"the device's limits do not hold this render on the GPU: \" + error.message, cpu);\n throw error;\n }\n if (output === null) return this.render(setup, signal, cpu);\n const { errorBound, diagnosticUncertaintySampleCount: uncertainty = 0, compositeProbe = null, ...rendered } = output;\n const execution: DisplayViewExecution = Object.freeze({ gpu: options.gpu, backend: \"webgpu-f32\", requestedBackend: \"webgpu-f32\", fallbackReason: null, arithmetic: \"float32\",\n assurance: \"approximation-with-a-priori-bound\", fast: true, bitIdenticalToReference: false, errorBound, diagnosticsExact: uncertainty === 0,\n diagnosticUncertaintySampleCount: uncertainty, limitations: WEBGPU_F32_LIMITATIONS, adapter, conformance: check, compositeProbe });\n return { rendered, execution };\n },\n dispose(): void {\n if (disposed) return;\n disposed = true;\n renderer.dispose?.();\n if (owned) runtime.destroy();\n }\n };\n}\n"]}
1
+ {"version":3,"file":"display-view-gpu-session.js","sourceRoot":"","sources":["../../src/facade/display-view-gpu-session.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * #481: the device handling behind `prepareDisplayView(request, { gpu: \"auto\" | \"require\", gpuDevice })`. Loaded on demand by\n * `simulate-display-view.ts`, so the GPU code stays out of bundles that never ask for it. One session per prepared view:\n *\n * - the realm's switch (`setWebGpuEnabled(false)`) vetoes before anything else: `\"auto\"` falls back with `webgpu-disabled`,\n * `\"require\"` throws it;\n * - with no renderer registered (the engine registers its renderer, the Speed and Quality kernels of #478 and #479, when this module\n * loads; a caller may replace it or set null) no device is requested: `unsupported-on-backend`;\n * - the device is the handle's (`gpuDevice`: an `ImageKernelAccelerator`'s device, shared and left to its owner, or a WebGPU\n * entry point to acquire from), or acquired from `navigator.gpu` and owned by the session; the accelerator's acquisition\n * reasons apply, and the request's `signal` aborts the acquisition;\n * - the renderer must support the request, else `unsupported-on-backend`; a render the renderer refuses only when rendering\n * (`unsupported-on-backend` thrown by `render`: a coarse view, a device that fails the composite chart probe, #491) runs the\n * CPU reference for that render with the same label, and so does a render whose tables or bands exceed the device's limits\n * (`insufficient-limits` thrown by `render`: #492, a large defocus kernel's table on a scene of many materials);\n * - before the first GPU render on the device a short conformance self-check runs once (single-flight): the built-in cases run\n * the existing `webgpu-f32` convolution kernel against the float64 reference within its a-priori bound, then the renderer's own\n * cases; a failure keeps the whole view on the CPU, labelled `conformance-failed`, with the adapter recorded; #594: cases of\n * code the renderer loads on demand (the Quality kernels) run once, before the first render that needs them, and a failure\n * there keeps that render and every later one on the CPU;\n * - GPU renders of one session run one at a time on the device (the accelerator's single flight; later renders wait);\n * - a lost device falls back to the CPU for that render and every later one, labelled `device-lost`; `dispose()` releases an\n * owned device, and later renders run on the CPU labelled `disposed`.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { getWebGpuEnabled } from \"../gpu/webgpu-switch.js\";\nimport { acquireWebGpuRuntime, type WebGpuRuntime } from \"../gpu/webgpu-runtime.js\";\nimport { ImageKernelExecutionError, WEBGPU_F32_LIMITATIONS, type ChartCompositeProbeRecord, type ImageKernelAdapterDescription } from \"../gpu/image-kernel-execution.js\";\nimport { acceleratorRuntime, convolveIrradianceOnRuntime } from \"../gpu/image-kernel-accelerator.js\";\nimport { calculateIrradianceConvolutionPlan, convolveIrradianceRows, type IrradianceConvolutionInput } from \"../optics/irradiance-convolution.js\";\nimport type { DisplayViewRenderResult, DisplayViewSetup } from \"./display-view.js\";\nimport { displayViewGpuRendererFactory as engineDisplayViewGpuRendererFactory } from \"../gpu/display-view-gpu-renderer.js\";\nimport { cpuDisplayViewExecution, displayViewGpuRendererFactory, setDisplayViewGpuRendererFactory, type DisplayViewExecution, type DisplayViewGpuConformance, type DisplayViewGpuConformanceCase,\n type DisplayViewGpuFallbackReason, type DisplayViewGpuRenderer, type DisplayViewGpuRequest, type ParsedPrepareDisplayViewOptions } from \"./display-view-gpu.js\";\n\n// #478, #479: the engine's own renderer, the display view's Speed and Quality kernels behind one renderer\n// (`src/gpu/display-view-quality-gpu.ts`), is registered when this module loads (that is, when a prepared view first asks for the\n// GPU) unless a caller registered a renderer before; a test that needs \"no renderer\" sets the factory to null.\nif (displayViewGpuRendererFactory() === null) setDisplayViewGpuRendererFactory(engineDisplayViewGpuRendererFactory);\n\n/** Internal: the GPU side of one prepared view. */\nexport interface DisplayViewGpuSession {\n /** Renders `setup` on the GPU when the session can, else through `cpu`; the label says which ran. */\n render(setup: DisplayViewSetup, signal: AbortSignal | undefined, cpu: () => Promise<DisplayViewRenderResult>): Promise<{ rendered: DisplayViewRenderResult; execution: DisplayViewExecution }>;\n dispose(): void;\n}\n\n/** A session that renders every view on the CPU with one fixed reason. */\nfunction cpuSession(options: ParsedPrepareDisplayViewOptions, reason: DisplayViewGpuFallbackReason, detail: string, adapter: ImageKernelAdapterDescription | null,\n conformance: DisplayViewGpuConformance | null): DisplayViewGpuSession {\n const execution = cpuDisplayViewExecution(options.gpu, reason, adapter, conformance, detail);\n return { async render(_setup, _signal, cpu): Promise<{ rendered: DisplayViewRenderResult; execution: DisplayViewExecution }> { return { rendered: await cpu(), execution }; },\n dispose(): void { /* nothing acquired */ } };\n}\n\n/** `\"require\"` throws the reason; `\"auto\"` gets a CPU session labelled with it. */\nfunction fallBack(options: ParsedPrepareDisplayViewOptions, reason: DisplayViewGpuFallbackReason, detail: string, adapter: ImageKernelAdapterDescription | null = null,\n conformance: DisplayViewGpuConformance | null = null): DisplayViewGpuSession {\n if (options.gpu === \"require\") throw requireError(reason, detail);\n return cpuSession(options, reason, detail, adapter, conformance);\n}\n/**\n * The error `\"require\"` throws instead of falling back. Every display-view fallback reason is also a failure reason of the accelerator's\n * error. A refusal by the composite chart probe carries its record as `probe` (the structured detail of the message).\n */\nfunction requireError(reason: DisplayViewGpuFallbackReason, detail: string, probe: ChartCompositeProbeRecord | null = null): ImageKernelExecutionError {\n const error = new ImageKernelExecutionError(reason, \"prepareDisplayView with gpu \\\"require\\\": \" + detail);\n if (probe) Object.defineProperty(error, \"probe\", { value: probe, enumerable: true });\n return error;\n}\n/** The composite chart probe's record on a refusal (`ChartCompositeProbeError.probe`), or null. */\nfunction probeOf(error: unknown): ChartCompositeProbeRecord | null {\n const probe = (error as { probe?: unknown }).probe;\n return typeof probe === \"object\" && probe !== null ? probe as ChartCompositeProbeRecord : null;\n}\n\n/** True for an object shaped like an `ImageKernelAccelerator` (the handle form that shares a device). */\nfunction isAccelerator(value: unknown): boolean {\n return typeof value === \"object\" && value !== null && typeof (value as { convolveIrradiance?: unknown }).convolveIrradiance === \"function\" &&\n typeof (value as { backend?: unknown }).backend === \"string\";\n}\n\n/**\n * Internal (#481): opens the GPU session of a prepared view, or throws (`\"require\"`) when the GPU cannot be used. Called only\n * for `gpu: \"auto\" | \"require\"`.\n */\nexport async function openDisplayViewGpuSession(options: ParsedPrepareDisplayViewOptions, request: DisplayViewGpuRequest, signal: AbortSignal | undefined): Promise<DisplayViewGpuSession> {\n if (!getWebGpuEnabled()) return fallBack(options, \"webgpu-disabled\", \"WebGPU is switched off in this realm (setWebGpuEnabled(false)).\");\n const factory = displayViewGpuRendererFactory();\n if (!factory) return fallBack(options, \"unsupported-on-backend\", \"this version of the engine has no GPU display-view renderer (#478); no device was requested.\");\n // #563: the lens signal (projection, distortion, vignetting, rotation) runs on the CPU reference only; no device is requested for it.\n if (request.lens) return fallBack(options, \"unsupported-on-backend\", \"the GPU display-view renderers do not render lens.projection, lens.distortion, lens.vignetting or \" +\n \"camera rotation (#563); the CPU reference renders them. No device was requested.\");\n // #597: an image-plane print under mixed light renders on the device (its Quality passes light each lattice point); charts keep the CPU.\n if (request.mixedIllumination && request.scene !== \"image-plane\") return fallBack(options, \"unsupported-on-backend\", \"the GPU renderers light chart materials with one illuminant; the CPU reference renders mixed illumination (#550). No device was requested.\");\n let runtime: WebGpuRuntime, owned = false;\n if (isAccelerator(options.gpuDevice)) {\n const shared = acceleratorRuntime(options.gpuDevice) as WebGpuRuntime | null | undefined;\n if (shared === undefined) throw new InvalidConfigurationError(\"prepareDisplayView options.gpuDevice must be an accelerator created by createImageKernelAccelerator.\");\n const accelerator = options.gpuDevice as { state: string; fallbackReason: DisplayViewGpuFallbackReason | null };\n if (accelerator.state === \"disposed\") throw new InvalidConfigurationError(\"prepareDisplayView options.gpuDevice is a disposed accelerator.\");\n if (shared === null) return fallBack(options, accelerator.fallbackReason ?? \"webgpu-unavailable\", \"the given accelerator runs the CPU reference and has no device.\");\n if (shared.isLost()) return fallBack(options, \"device-lost\", \"the given accelerator's device was lost.\", shared.adapter);\n runtime = shared;\n } else {\n const gpu = options.gpuDevice !== undefined ? options.gpuDevice : (globalThis as { navigator?: { gpu?: unknown } }).navigator?.gpu;\n let acquired: Awaited<ReturnType<typeof acquireWebGpuRuntime>>;\n try { acquired = await acquireWebGpuRuntime(gpu, undefined, signal); }\n catch (error) {\n if (error instanceof ImageKernelExecutionError && error.reason === \"aborted\") throw new InvalidConfigurationError(\"prepareDisplayView aborted.\");\n throw error;\n }\n if (\"failure\" in acquired) return fallBack(options, acquired.failure, acquired.message);\n runtime = acquired.runtime; owned = true;\n }\n const renderer = factory(runtime), supported = renderer.supports(request);\n if (supported !== true) {\n if (owned) runtime.destroy();\n return fallBack(options, \"unsupported-on-backend\", \"the GPU display-view renderer \\\"\" + renderer.id + \"\\\" does not support this request: \" + supported, runtime.adapter);\n }\n return createSession(options, runtime, owned, renderer);\n}\n\n// ---------------------------------------------------------------------------------------------------------------\n// Run-time conformance self-check.\n\n/** A fixed, seeded test image (mulberry32) for the built-in cases. */\nfunction seededSamples(count: number, seed: number): Float64Array {\n let a = seed >>> 0;\n const out = new Float64Array(count);\n for (let i = 0; i < count; i++) {\n a = (a + 0x6d2b79f5) >>> 0;\n let t = Math.imul(a ^ (a >>> 15), 1 | a);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n const u = ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n out[i] = u < 0.05 ? 0 : 10 ** (u * 6 - 3);\n }\n return out;\n}\n/** One convolution case: normalized Gaussian kernels of width `sigma` per patch, compared with the float64 reference within the a-priori bound. */\nfunction convolutionCase(id: string, width: number, height: number, radius: number, patchWidth: number, patchHeight: number, seed: number): DisplayViewGpuConformanceCase {\n return { id, async run(runtime, signal): Promise<true | string> {\n const size = 2 * radius + 1, taps = size * size, columns = Math.ceil(width / patchWidth), rows = Math.ceil(height / patchHeight);\n const kernels = new Float64Array(columns * rows * taps);\n for (let p = 0; p < columns * rows; p++) {\n const sigma = 0.6 + 0.4 * (p % 3), scale = 0.8 + 0.05 * p;\n let sum = 0;\n for (let v = -radius; v <= radius; v++) for (let u = -radius; u <= radius; u++) { const w = Math.exp(-0.5 * (u * u + v * v) / (sigma * sigma)); kernels[p * taps + (v + radius) * size + u + radius] = w; sum += w; }\n for (let t = 0; t < taps; t++) kernels[p * taps + t] = kernels[p * taps + t]! / sum * Math.min(1, scale);\n }\n const input: IrradianceConvolutionInput = { schemaVersion: \"0.1.0\", width, height, kernelRadius: radius, patchWidth, patchHeight, boundary: \"zero-outside-grid\",\n samples: seededSamples(width * height, seed), kernels };\n const plan = calculateIrradianceConvolutionPlan(input), reference = new Float64Array(width * height);\n convolveIrradianceRows(plan, input.samples, input.kernels, 0, height, reference);\n {\n const result = await convolveIrradianceOnRuntime(runtime, input, signal);\n const bound = result.execution.errorBound;\n if (!bound || bound.kind !== \"relative-to-reference\") return \"the convolution reported no relative bound.\";\n let worst = 0, worstIndex = -1;\n for (let i = 0; i < reference.length; i++) {\n const allowed = bound.relative * reference[i]! + bound.absolute, excess = Math.abs(result.values[i]! - reference[i]!) - allowed;\n if (excess > worst) { worst = excess; worstIndex = i; }\n }\n return worstIndex < 0 ? true : \"sample \" + worstIndex + \" differs from the reference by \" + Math.abs(result.values[worstIndex]! - reference[worstIndex]!) +\n \", more than the a-priori bound \" + (bound.relative * reference[worstIndex]! + bound.absolute) + \".\";\n }\n } };\n}\n/** The built-in cases, run on every device before its first display-view render: the existing convolution kernel on two small images. */\nexport const DISPLAY_VIEW_GPU_BUILT_IN_CASES: readonly DisplayViewGpuConformanceCase[] = Object.freeze([\n convolutionCase(\"image-kernel:convolution:16x12-r1\", 16, 12, 1, 16, 12, 481),\n convolutionCase(\"image-kernel:convolution:32x24-r3-patches\", 32, 24, 3, 16, 12, 4781)\n]);\n\n/**\n * Runs `cases` in order and returns the record. `before` is a record that already passed (#594: the cases run at the device's\n * first render, when `cases` are a renderer's on-demand cases); its ids come first in the record.\n */\nasync function runConformance(runtime: WebGpuRuntime, cases: readonly DisplayViewGpuConformanceCase[], signal: AbortSignal | undefined,\n before: DisplayViewGpuConformance | null = null): Promise<DisplayViewGpuConformance> {\n const ids = Object.freeze([...(before?.cases ?? []), ...cases.map((c) => c.id)]);\n for (const c of cases) {\n let outcome: true | string;\n try { outcome = await c.run(runtime, signal); }\n catch (error) {\n // An abort is the caller's, not the device's; everything else the device did wrong is a failed case.\n if (error instanceof ImageKernelExecutionError && error.reason === \"aborted\") throw error;\n outcome = \"the case threw \" + (error instanceof ImageKernelExecutionError ? error.reason + \": \" : \"\") + (error instanceof Error ? error.message : String(error));\n }\n if (outcome !== true) return Object.freeze({ cases: ids, passed: false, failedCase: c.id, detail: outcome });\n }\n return Object.freeze({ cases: ids, passed: true, failedCase: null, detail: null });\n}\n\n// ---------------------------------------------------------------------------------------------------------------\n\n/** #594: the error of on-demand renderer code that could not be loaded. */\nfunction qualityCodeUnavailable(error: unknown): boolean {\n return error instanceof ImageKernelExecutionError && error.reason === \"quality-code-unavailable\";\n}\n\nfunction createSession(options: ParsedPrepareDisplayViewOptions, runtime: WebGpuRuntime, owned: boolean, renderer: DisplayViewGpuRenderer): DisplayViewGpuSession {\n const adapter = runtime.adapter;\n let disposed = false, lost = false, conformance: DisplayViewGpuConformance | null = null, checking: Promise<DisplayViewGpuConformance> | null = null;\n /** The last GPU turn: renders queue behind it, so one dispatch runs at a time on the device. */\n let tail: Promise<unknown> = Promise.resolve();\n /** A CPU fallback label for `\"auto\"`; with `\"require\"` the same event is an error. */\n const fallback = async (reason: DisplayViewGpuFallbackReason, detail: string, cpu: () => Promise<DisplayViewRenderResult>, compositeProbe: ChartCompositeProbeRecord | null = null):\n Promise<{ rendered: DisplayViewRenderResult; execution: DisplayViewExecution }> => {\n if (options.gpu === \"require\") throw requireError(reason, detail, compositeProbe);\n return { rendered: await cpu(), execution: cpuDisplayViewExecution(options.gpu, reason, adapter, conformance, detail, compositeProbe) };\n };\n /** The self-check, run once per session (single flight); a failing check is remembered and never repeated. */\n function selfCheck(signal: AbortSignal | undefined): Promise<DisplayViewGpuConformance> {\n if (conformance) return Promise.resolve(conformance);\n if (!checking) {\n checking = runConformance(runtime, [...DISPLAY_VIEW_GPU_BUILT_IN_CASES, ...(renderer.conformanceCases ?? [])], signal).then((result) => { conformance = result; return result; }, (error: unknown) => { checking = null; throw error; });\n }\n return checking;\n }\n /**\n * #594: the renderer's on-demand cases for a render (the Quality kernels' self-check, owner decision 2026-11-10), run once\n * after the device's own check passed (single flight); the record then lists both and replaces the session's record, so a\n * failure keeps this render and every later one on the CPU, as a failure at the first render does.\n */\n let onDemand: Promise<DisplayViewGpuConformance> | null = null;\n function onDemandCheck(setup: DisplayViewSetup, passed: DisplayViewGpuConformance, signal: AbortSignal | undefined): Promise<DisplayViewGpuConformance> {\n if (onDemand) return onDemand;\n const cases = renderer.onDemandConformanceCases?.(setup);\n if (!cases) return Promise.resolve(passed);\n return onDemand = cases.then((list) => runConformance(runtime, list, signal, passed)).then((result) => conformance = result,\n (error: unknown) => { onDemand = null; throw error; });\n }\n function lostError(error: unknown): boolean { return (error instanceof ImageKernelExecutionError && error.reason === \"device-lost\") || runtime.isLost(); }\n return {\n async render(setup, signal, cpu): Promise<{ rendered: DisplayViewRenderResult; execution: DisplayViewExecution }> {\n if (disposed) return fallback(\"disposed\", \"the prepared view was disposed.\", cpu);\n if (lost || runtime.isLost()) { lost = true; return fallback(\"device-lost\", \"the WebGPU device was lost; the rest of the view runs on the CPU.\", cpu); }\n let check: DisplayViewGpuConformance;\n try {\n check = await selfCheck(signal);\n if (check.passed) check = await onDemandCheck(setup, check, signal);\n }\n catch (error) {\n if (lostError(error)) { lost = true; return fallback(\"device-lost\", \"the WebGPU device was lost during its conformance check.\", cpu); }\n // #594: the on-demand code did not load: this render runs the CPU reference; the next one that needs it tries again.\n if (qualityCodeUnavailable(error)) return fallback(\"quality-code-unavailable\", (error as Error).message, cpu);\n setup.checkAbort();\n throw error;\n }\n if (!check.passed) return fallback(\"conformance-failed\", \"the device failed conformance case \\\"\" + check.failedCase + \"\\\": \" + check.detail, cpu);\n const turn = tail.then(async () => {\n if (disposed || lost || runtime.isLost()) return null;\n setup.checkAbort();\n return renderer.render({ setup, signal });\n });\n tail = turn.catch(() => undefined);\n let output: Awaited<typeof turn>;\n try { output = await turn; }\n catch (error) {\n if (lostError(error)) { lost = true; return fallback(\"device-lost\", \"the WebGPU device was lost during a render; the rest of the view runs on the CPU.\", cpu); }\n setup.checkAbort();\n if (qualityCodeUnavailable(error)) return fallback(\"quality-code-unavailable\", (error as Error).message, cpu);\n if (error instanceof ImageKernelExecutionError && error.reason === \"unsupported-on-backend\")\n return fallback(\"unsupported-on-backend\", \"the GPU display-view renderer \\\"\" + renderer.id + \"\\\" does not cover this render: \" + error.message, cpu, probeOf(error));\n // #492: a render past the device's limits (a kernel table or band above its storage binding limit) runs the CPU reference too.\n if (error instanceof ImageKernelExecutionError && error.reason === \"insufficient-limits\")\n return fallback(\"insufficient-limits\", \"the device's limits do not hold this render on the GPU: \" + error.message, cpu);\n throw error;\n }\n if (output === null) return this.render(setup, signal, cpu);\n const { errorBound, diagnosticUncertaintySampleCount: uncertainty = 0, compositeProbe = null, ...rendered } = output;\n const execution: DisplayViewExecution = Object.freeze({ gpu: options.gpu, backend: \"webgpu-f32\", requestedBackend: \"webgpu-f32\", fallbackReason: null, arithmetic: \"float32\",\n assurance: \"approximation-with-a-priori-bound\", fast: true, bitIdenticalToReference: false, errorBound, diagnosticsExact: uncertainty === 0,\n diagnosticUncertaintySampleCount: uncertainty, limitations: WEBGPU_F32_LIMITATIONS, adapter, conformance: check, compositeProbe });\n return { rendered, execution };\n },\n dispose(): void {\n if (disposed) return;\n disposed = true;\n renderer.dispose?.();\n if (owned) runtime.destroy();\n }\n };\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  import type { ChartCompositeProbeRecord, ImageKernelAdapterDescription, ImageKernelExecution, ImageKernelFallbackReason } from "../gpu/image-kernel-execution.js";
2
2
  import type { DisplayViewRenderResult, DisplayViewSetup } from "./display-view.js";
3
3
  import type { SimulateCaptureFastReport } from "./simulate-capture.js";
4
+ import type { SdrToneCurve } from "../output/sdr-rendering.js";
4
5
  /**
5
6
  * 2.11 (#481): whether a prepared display view may render on the GPU. `"off"` (the default) is the CPU reference, today's
6
7
  * behaviour byte for byte. `"auto"` renders on WebGPU when a conforming device is available and the request is supported, and
@@ -34,9 +35,11 @@ export declare function parsePrepareDisplayViewOptions(value: unknown, fast?: bo
34
35
  * 2.11 (#481): why a display view that asked for the GPU (`gpu: "auto"`) ran the CPU reference. The accelerator's acquisition
35
36
  * reasons, plus: `unsupported-on-backend` (no GPU display-view renderer exists in this version, or it does not support the
36
37
  * request), `conformance-failed` (the device failed the run-time self-check before the view's first GPU render), `device-lost`
37
- * (the device was lost; the rest of the view runs on the CPU) and `disposed` (the prepared view was disposed).
38
+ * (the device was lost; the rest of the view runs on the CPU) and `disposed` (the prepared view was disposed). 2.22.0 (#594):
39
+ * `quality-code-unavailable` (the on-demand GPU full-quality code could not be loaded; that render runs the CPU reference, and
40
+ * the next render that needs the code tries to load it again).
38
41
  */
39
- export type DisplayViewGpuFallbackReason = ImageKernelFallbackReason | "unsupported-on-backend" | "conformance-failed" | "device-lost" | "disposed";
42
+ export type DisplayViewGpuFallbackReason = ImageKernelFallbackReason | "unsupported-on-backend" | "conformance-failed" | "device-lost" | "disposed" | "quality-code-unavailable";
40
43
  /** 2.11 (#481): the run-time conformance self-check of a device, run once before the view's first GPU render. */
41
44
  export interface DisplayViewGpuConformance {
42
45
  /** The ids of the cases run, in order (the built-in image-kernel cases, then the renderer's own). */
@@ -92,7 +95,9 @@ export interface DisplayViewGpuRequest {
92
95
  antiAliasing: boolean;
93
96
  /** Pixel-aperture samples per axis (1: centre sampling). */
94
97
  boxSamples: number;
95
- toneCurve: "identity" | "positive-reinhard-per-channel";
98
+ toneCurve: SdrToneCurve;
99
+ /** #593, #601: true with `highlightMode: "reconstruct"` or `gamutHandling: "desaturate-to-luminance"` (coupled rendering steps). */
100
+ coupled?: boolean;
96
101
  /**
97
102
  * #492: true when `lens.defocus` needs the defocus disc (out of focus): the expected signal then carries the disc, or each
98
103
  * node's diffraction kernel convolved with it, as site kernels (#492 step 2b), which the engine's renderer gathers in its
@@ -143,14 +148,17 @@ export interface DisplayViewGpuConformanceCase {
143
148
  * for those two events, as the accelerator's operations do; a render that throws `unsupported-on-backend` (a request the
144
149
  * renderer finds it does not cover only when rendering) runs the CPU reference labelled with that reason, or fails with it under
145
150
  * `"require"`. `conformanceCases` are run after the built-in image-kernel cases before the device's first render; a failure keeps
146
- * the whole view on the CPU. `dispose` releases what the renderer holds on the device (#491: uploaded scene records); the session
147
- * calls it when the prepared view is disposed.
151
+ * the whole view on the CPU. #594: `onDemandConformanceCases` returns the cases a render needs beyond those (code the renderer
152
+ * loads on demand, such as the Quality kernels), or null; they run once, before the first render that returns them, and their
153
+ * ids are appended to the conformance record; a failure keeps that render and every later one on the CPU. `dispose` releases
154
+ * what the renderer holds on the device (#491: uploaded scene records); the session calls it when the prepared view is disposed.
148
155
  */
149
156
  export interface DisplayViewGpuRenderer {
150
157
  readonly id: string;
151
158
  supports(request: DisplayViewGpuRequest): true | string;
152
159
  render(part: DisplayViewGpuPart): Promise<DisplayViewGpuRenderOutput>;
153
160
  readonly conformanceCases?: readonly DisplayViewGpuConformanceCase[];
161
+ onDemandConformanceCases?(setup: DisplayViewSetup): Promise<readonly DisplayViewGpuConformanceCase[]> | null;
154
162
  dispose?(): void;
155
163
  }
156
164
  export type DisplayViewGpuRendererFactory = (runtime: DisplayViewGpuRuntimeHandle) => DisplayViewGpuRenderer;
@@ -1 +1 @@
1
- {"version":3,"file":"display-view-gpu.js","sourceRoot":"","sources":["../../src/facade/display-view-gpu.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * #481: how a prepared display view chooses between a WebGPU preview renderer and the CPU reference, and how a render labels\n * which ran. This module holds the option, the label and the renderer contract and imports nothing from the GPU code, so a\n * bundle that never asks for the GPU (`gpu: \"off\"`, the default) does not contain it; the device handling lives in\n * `display-view-gpu-session.ts`, loaded on demand by `prepareDisplayView` when `gpu` is `\"auto\"` or `\"require\"`.\n *\n * The vocabulary is the image-kernel accelerator's (`createImageKernelAccelerator`, docs/WEBGPU.md): `\"auto\"` is\n * `backend: \"webgpu-f32\"` with `fallback: \"cpu-reference\"`, `\"require\"` is `fallback: \"fail\"`, `\"off\"` is\n * `backend: \"cpu-reference\"`. The render's `diagnostics.fast.execution` names the backend that ran, the fallback reason and the\n * bound in the fields of `ImageKernelExecution`, plus the adapter and the run-time conformance check.\n *\n * No GPU display-view renderer exists yet (#478, #479): until one registers itself through {@link setDisplayViewGpuRendererFactory},\n * `\"auto\"` runs the CPU reference labelled `unsupported-on-backend` without touching a device, and `\"require\"` fails with that reason.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport type { ChartCompositeProbeRecord, ImageKernelAdapterDescription, ImageKernelBackend, ImageKernelExecution, ImageKernelFallbackReason } from \"../gpu/image-kernel-execution.js\";\nimport type { DisplayViewRenderResult, DisplayViewSetup } from \"./display-view.js\";\nimport type { SimulateCaptureFastReport } from \"./simulate-capture.js\";\n\n/**\n * 2.11 (#481): whether a prepared display view may render on the GPU. `\"off\"` (the default) is the CPU reference, today's\n * behaviour byte for byte. `\"auto\"` renders on WebGPU when a conforming device is available and the request is supported, and\n * otherwise runs the CPU reference and says why. `\"require\"` fails instead of falling back. In the accelerator's words: `\"auto\"`\n * is `backend: \"webgpu-f32\"` with `fallback: \"cpu-reference\"`, `\"require\"` is `fallback: \"fail\"`, `\"off\"` is `backend: \"cpu-reference\"`.\n */\nexport type DisplayViewGpuMode = \"off\" | \"auto\" | \"require\";\n\n/** 2.11 (#481): the second argument of `prepareDisplayView`. */\nexport interface PrepareDisplayViewOptions {\n /**\n * See {@link DisplayViewGpuMode}. 2.20.0: default `\"auto\"` when the request resolves to fast (`fast` omitted or true: the\n * display view's default) and `\"off\"` when it is exact (`fast: false`); an explicit value wins.\n */\n gpu?: DisplayViewGpuMode;\n /**\n * Where the device comes from, with `gpu: \"auto\"` or `\"require\"`: a WebGPU entry point (a worker's `navigator.gpu`), or an\n * `ImageKernelAccelerator` whose device the view shares (the accelerator keeps ownership; `dispose()` of the prepared view\n * leaves it alone). Without it the engine acquires a device from `globalThis.navigator.gpu` and owns it until `dispose()`.\n * Refused when `gpu` is or defaults to `\"off\"`.\n */\n gpuDevice?: unknown;\n}\n\n/** The parsed form of {@link PrepareDisplayViewOptions}. @internal */\nexport interface ParsedPrepareDisplayViewOptions { gpu: DisplayViewGpuMode; gpuDevice: unknown }\n\n/** Internal: validates the second argument of `prepareDisplayView`; `fast` is the request's resolved top-level fast (the GPU default). */\nexport function parsePrepareDisplayViewOptions(value: unknown, fast = false): ParsedPrepareDisplayViewOptions {\n if (value === undefined) value = {};\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) throw new InvalidConfigurationError(\"prepareDisplayView options must be an object { gpu, gpuDevice }.\");\n for (const key of Object.keys(value)) if (key !== \"gpu\" && key !== \"gpuDevice\") throw new InvalidConfigurationError(\"Unknown prepareDisplayView options field: \" + key + \".\");\n const { gpu, gpuDevice } = value as Record<string, unknown>;\n const mode: DisplayViewGpuMode = gpu === undefined ? fast ? \"auto\" : \"off\" : gpu as DisplayViewGpuMode;\n if (mode !== \"off\" && mode !== \"auto\" && mode !== \"require\") throw new InvalidConfigurationError(\"prepareDisplayView options.gpu must be \\\"off\\\", \\\"auto\\\" or \\\"require\\\".\");\n if (gpuDevice !== undefined && (typeof gpuDevice !== \"object\" || gpuDevice === null)) throw new InvalidConfigurationError(\"prepareDisplayView options.gpuDevice must be a WebGPU entry point (navigator.gpu) or an ImageKernelAccelerator.\");\n if (gpuDevice !== undefined && mode === \"off\") throw new InvalidConfigurationError(\"prepareDisplayView options.gpuDevice needs gpu \\\"auto\\\" or \\\"require\\\".\");\n return { gpu: mode, gpuDevice };\n}\n\n/**\n * 2.11 (#481): why a display view that asked for the GPU (`gpu: \"auto\"`) ran the CPU reference. The accelerator's acquisition\n * reasons, plus: `unsupported-on-backend` (no GPU display-view renderer exists in this version, or it does not support the\n * request), `conformance-failed` (the device failed the run-time self-check before the view's first GPU render), `device-lost`\n * (the device was lost; the rest of the view runs on the CPU) and `disposed` (the prepared view was disposed).\n */\nexport type DisplayViewGpuFallbackReason = ImageKernelFallbackReason | \"unsupported-on-backend\" | \"conformance-failed\" | \"device-lost\" | \"disposed\";\n\n/** 2.11 (#481): the run-time conformance self-check of a device, run once before the view's first GPU render. */\nexport interface DisplayViewGpuConformance {\n /** The ids of the cases run, in order (the built-in image-kernel cases, then the renderer's own). */\n cases: readonly string[];\n passed: boolean;\n /** The first case that failed, or null. */\n failedCase: string | null;\n /** What the failed case reported, or null. */\n detail: string | null;\n}\n\n/**\n * 2.11 (#481): where a display view's render ran, in the words of the image-kernel execution record (`ImageKernelExecution`):\n * `backend` names the path that ran (`cpu-reference`, the float64 engine reference, or `webgpu-f32`, a float32 approximation\n * within `errorBound`), `requestedBackend` what `gpu` asked for, and `fallbackReason` why a request for the GPU ran the CPU.\n * `adapter` describes the device's adapter whenever one was involved, also when the view then fell back; `conformance` is\n * the device's self-check once it has run. A CPU render keeps `assurance: \"engine-reference\"` and `fast: false`.\n */\nexport interface DisplayViewExecution extends Omit<ImageKernelExecution, \"fallbackReason\"> {\n /** The `gpu` option the view was prepared with. */\n gpu: DisplayViewGpuMode;\n fallbackReason: DisplayViewGpuFallbackReason | null;\n adapter: ImageKernelAdapterDescription | null;\n conformance: DisplayViewGpuConformance | null;\n /**\n * 2.11: the composite chart kernel's device probe when this render needed it (composite charts, the 2.3 elements and\n * `material-layers` scenes): the device class and the product path the kernel ran with, or, on a refusal (`fallbackReason`\n * `unsupported-on-backend`), why. Null when the render did not run the probe (the 2.0 presets, `gpu: \"off\"`).\n */\n compositeProbe: ChartCompositeProbeRecord | null;\n}\n\n/** 2.11 (#481): `diagnostics.fast` of a display view: the capture's report plus where the render ran. */\nexport interface DisplayViewFastReport extends SimulateCaptureFastReport {\n /** Where this render ran (see {@link DisplayViewExecution}). `assurance` above follows it. */\n execution: DisplayViewExecution;\n}\n\nconst CPU_LIMITATIONS = /* @__PURE__ */ Object.freeze([\"Float64 engine reference execution; results are the reference by definition\"]);\n\n/** Internal: the execution record of a display view rendered on the CPU reference. `requested` names what `gpu` asked for. */\nexport function cpuDisplayViewExecution(gpu: DisplayViewGpuMode, fallbackReason: DisplayViewGpuFallbackReason | null, adapter: ImageKernelAdapterDescription | null,\n conformance: DisplayViewGpuConformance | null, detail?: string, compositeProbe: ChartCompositeProbeRecord | null = null): DisplayViewExecution {\n const requestedBackend: ImageKernelBackend = gpu === \"off\" ? \"cpu-reference\" : \"webgpu-f32\";\n const limitations = detail === undefined ? CPU_LIMITATIONS : Object.freeze([...CPU_LIMITATIONS, \"WebGPU was requested (gpu: \\\"\" + gpu + \"\\\") and the CPU reference ran: \" + detail]);\n return Object.freeze({ gpu, backend: \"cpu-reference\", requestedBackend, fallbackReason, arithmetic: \"float64\", assurance: \"engine-reference\", fast: false,\n bitIdenticalToReference: true, errorBound: null, diagnosticsExact: true, diagnosticUncertaintySampleCount: 0, limitations, adapter, conformance, compositeProbe });\n}\n\n// ---------------------------------------------------------------------------------------------------------------\n// The renderer contract (#478 implements it; until then the only implementation is a test fake).\n\n/**\n * Internal (#481): the device a renderer or conformance case runs on. It is the engine's `WebGpuRuntime` object\n * (`src/gpu/webgpu-runtime.ts`: `device`, `guard`, `destroy` and the rest), seen here through its WebGPU-free members only so\n * that no WebGPU type reaches the published declarations (docs/WEBGPU.md); a renderer in the engine casts it to `WebGpuRuntime`.\n */\nexport interface DisplayViewGpuRuntimeHandle {\n readonly adapter: ImageKernelAdapterDescription | null;\n readonly maximumStorageBindingBytes: number;\n readonly maximumWorkgroupsPerDimension: number;\n isLost(): boolean;\n}\n\n/** What a prepared request asks of a GPU renderer (`supports`): the options that shape a render. */\nexport interface DisplayViewGpuRequest {\n ahd: boolean;\n diffraction: boolean;\n antiAliasing: boolean;\n /** Pixel-aperture samples per axis (1: centre sampling). */\n boxSamples: number;\n toneCurve: \"identity\" | \"positive-reinhard-per-channel\";\n /**\n * #492: true when `lens.defocus` needs the defocus disc (out of focus): the expected signal then carries the disc, or each\n * node's diffraction kernel convolved with it, as site kernels (#492 step 2b), which the engine's renderer gathers in its\n * Quality site pass (step 2c). Absent or false otherwise.\n */\n defocus?: boolean;\n /**\n * #564: true when the defocus kernel's radius is above 64 sites, so the expected signal convolves it by runs on the CPU\n * (`largeKernel`); no GPU renderer takes it. Absent or false otherwise.\n */\n largeDefocus?: boolean;\n /**\n * #563: true when the request has `lens.projection`, `lens.distortion`, `lens.vignetting` or camera rotation: the CPU reference\n * renders it (display-view-lens-signal.ts) and no GPU renderer is asked or device requested (`unsupported-on-backend`).\n */\n lens?: boolean;\n /**\n * #550: true when the request has `illumination` (mixed lighting): the radiance at a point is no longer a function of its\n * material, so the GPU material lookup cannot render it; the CPU reference does, exactly, and no device is requested.\n */\n mixedIllumination?: boolean;\n /** The scene's form: an engine chart, a declared `material-layers` scene (#491), or a caller function. */\n scene: \"chart\" | \"material-layers\" | \"material-function\" | \"reflectance-function\" | \"radiance-function\" | \"image-plane\";\n}\n/** One render of a region: the CPU renderer's own setup (tables, readout, demosaic, region, callbacks) and the render's signal. */\nexport interface DisplayViewGpuPart { setup: DisplayViewSetup; signal: AbortSignal | undefined }\n/** What a GPU render returns: the CPU renderer's result shape plus the a-priori bound of its values against the reference. */\nexport interface DisplayViewGpuRenderOutput extends DisplayViewRenderResult {\n errorBound: NonNullable<ImageKernelExecution[\"errorBound\"]>;\n /** Samples whose float32 classification fell inside its bound (0 when none). */\n diagnosticUncertaintySampleCount?: number;\n /** The composite chart kernel's device probe record, when the render used the composite material module. */\n compositeProbe?: ChartCompositeProbeRecord;\n}\n/** A conformance case: returns `true` when the device agrees with the reference within the case's bound, or a sentence saying how it did not. */\nexport interface DisplayViewGpuConformanceCase { id: string; run(runtime: DisplayViewGpuRuntimeHandle, signal: AbortSignal | undefined): Promise<true | string> }\n/**\n * Internal (#481): the contract a GPU display-view renderer fulfils (#478). One instance serves one device, created by the\n * registered factory for each prepared view that acquires or shares a device. `supports` says whether the renderer covers a\n * prepared request (`true`) or why not (a sentence; the view then runs the CPU reference labelled `unsupported-on-backend`).\n * `render` renders one region on the device and must throw `ImageKernelExecutionError` with reason `device-lost` or `aborted`\n * for those two events, as the accelerator's operations do; a render that throws `unsupported-on-backend` (a request the\n * renderer finds it does not cover only when rendering) runs the CPU reference labelled with that reason, or fails with it under\n * `\"require\"`. `conformanceCases` are run after the built-in image-kernel cases before the device's first render; a failure keeps\n * the whole view on the CPU. `dispose` releases what the renderer holds on the device (#491: uploaded scene records); the session\n * calls it when the prepared view is disposed.\n */\nexport interface DisplayViewGpuRenderer {\n readonly id: string;\n supports(request: DisplayViewGpuRequest): true | string;\n render(part: DisplayViewGpuPart): Promise<DisplayViewGpuRenderOutput>;\n readonly conformanceCases?: readonly DisplayViewGpuConformanceCase[];\n dispose?(): void;\n}\nexport type DisplayViewGpuRendererFactory = (runtime: DisplayViewGpuRuntimeHandle) => DisplayViewGpuRenderer;\n\nlet rendererFactory: DisplayViewGpuRendererFactory | null = null;\n/**\n * Internal (#481): registers the renderer that `prepareDisplayView` uses for `gpu: \"auto\" | \"require\"`, and returns the one\n * registered before (null: none). #478's renderer registers itself here; tests register a fake. With none registered no device\n * is requested and every GPU request falls back (or fails) with `unsupported-on-backend`.\n */\nexport function setDisplayViewGpuRendererFactory(factory: DisplayViewGpuRendererFactory | null): DisplayViewGpuRendererFactory | null {\n if (factory !== null && typeof factory !== \"function\") throw new InvalidConfigurationError(\"setDisplayViewGpuRendererFactory expects a function or null.\");\n const previous = rendererFactory;\n rendererFactory = factory;\n return previous;\n}\n/** Internal: the registered factory. */\nexport function displayViewGpuRendererFactory(): DisplayViewGpuRendererFactory | null { return rendererFactory; }\n"]}
1
+ {"version":3,"file":"display-view-gpu.js","sourceRoot":"","sources":["../../src/facade/display-view-gpu.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * #481: how a prepared display view chooses between a WebGPU preview renderer and the CPU reference, and how a render labels\n * which ran. This module holds the option, the label and the renderer contract and imports nothing from the GPU code, so a\n * bundle that never asks for the GPU (`gpu: \"off\"`, the default) does not contain it; the device handling lives in\n * `display-view-gpu-session.ts`, loaded on demand by `prepareDisplayView` when `gpu` is `\"auto\"` or `\"require\"`.\n *\n * The vocabulary is the image-kernel accelerator's (`createImageKernelAccelerator`, docs/WEBGPU.md): `\"auto\"` is\n * `backend: \"webgpu-f32\"` with `fallback: \"cpu-reference\"`, `\"require\"` is `fallback: \"fail\"`, `\"off\"` is\n * `backend: \"cpu-reference\"`. The render's `diagnostics.fast.execution` names the backend that ran, the fallback reason and the\n * bound in the fields of `ImageKernelExecution`, plus the adapter and the run-time conformance check.\n *\n * No GPU display-view renderer exists yet (#478, #479): until one registers itself through {@link setDisplayViewGpuRendererFactory},\n * `\"auto\"` runs the CPU reference labelled `unsupported-on-backend` without touching a device, and `\"require\"` fails with that reason.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport type { ChartCompositeProbeRecord, ImageKernelAdapterDescription, ImageKernelBackend, ImageKernelExecution, ImageKernelFallbackReason } from \"../gpu/image-kernel-execution.js\";\nimport type { DisplayViewRenderResult, DisplayViewSetup } from \"./display-view.js\";\nimport type { SimulateCaptureFastReport } from \"./simulate-capture.js\";\nimport type { SdrToneCurve } from \"../output/sdr-rendering.js\";\n\n/**\n * 2.11 (#481): whether a prepared display view may render on the GPU. `\"off\"` (the default) is the CPU reference, today's\n * behaviour byte for byte. `\"auto\"` renders on WebGPU when a conforming device is available and the request is supported, and\n * otherwise runs the CPU reference and says why. `\"require\"` fails instead of falling back. In the accelerator's words: `\"auto\"`\n * is `backend: \"webgpu-f32\"` with `fallback: \"cpu-reference\"`, `\"require\"` is `fallback: \"fail\"`, `\"off\"` is `backend: \"cpu-reference\"`.\n */\nexport type DisplayViewGpuMode = \"off\" | \"auto\" | \"require\";\n\n/** 2.11 (#481): the second argument of `prepareDisplayView`. */\nexport interface PrepareDisplayViewOptions {\n /**\n * See {@link DisplayViewGpuMode}. 2.20.0: default `\"auto\"` when the request resolves to fast (`fast` omitted or true: the\n * display view's default) and `\"off\"` when it is exact (`fast: false`); an explicit value wins.\n */\n gpu?: DisplayViewGpuMode;\n /**\n * Where the device comes from, with `gpu: \"auto\"` or `\"require\"`: a WebGPU entry point (a worker's `navigator.gpu`), or an\n * `ImageKernelAccelerator` whose device the view shares (the accelerator keeps ownership; `dispose()` of the prepared view\n * leaves it alone). Without it the engine acquires a device from `globalThis.navigator.gpu` and owns it until `dispose()`.\n * Refused when `gpu` is or defaults to `\"off\"`.\n */\n gpuDevice?: unknown;\n}\n\n/** The parsed form of {@link PrepareDisplayViewOptions}. @internal */\nexport interface ParsedPrepareDisplayViewOptions { gpu: DisplayViewGpuMode; gpuDevice: unknown }\n\n/** Internal: validates the second argument of `prepareDisplayView`; `fast` is the request's resolved top-level fast (the GPU default). */\nexport function parsePrepareDisplayViewOptions(value: unknown, fast = false): ParsedPrepareDisplayViewOptions {\n if (value === undefined) value = {};\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) throw new InvalidConfigurationError(\"prepareDisplayView options must be an object { gpu, gpuDevice }.\");\n for (const key of Object.keys(value)) if (key !== \"gpu\" && key !== \"gpuDevice\") throw new InvalidConfigurationError(\"Unknown prepareDisplayView options field: \" + key + \".\");\n const { gpu, gpuDevice } = value as Record<string, unknown>;\n const mode: DisplayViewGpuMode = gpu === undefined ? fast ? \"auto\" : \"off\" : gpu as DisplayViewGpuMode;\n if (mode !== \"off\" && mode !== \"auto\" && mode !== \"require\") throw new InvalidConfigurationError(\"prepareDisplayView options.gpu must be \\\"off\\\", \\\"auto\\\" or \\\"require\\\".\");\n if (gpuDevice !== undefined && (typeof gpuDevice !== \"object\" || gpuDevice === null)) throw new InvalidConfigurationError(\"prepareDisplayView options.gpuDevice must be a WebGPU entry point (navigator.gpu) or an ImageKernelAccelerator.\");\n if (gpuDevice !== undefined && mode === \"off\") throw new InvalidConfigurationError(\"prepareDisplayView options.gpuDevice needs gpu \\\"auto\\\" or \\\"require\\\".\");\n return { gpu: mode, gpuDevice };\n}\n\n/**\n * 2.11 (#481): why a display view that asked for the GPU (`gpu: \"auto\"`) ran the CPU reference. The accelerator's acquisition\n * reasons, plus: `unsupported-on-backend` (no GPU display-view renderer exists in this version, or it does not support the\n * request), `conformance-failed` (the device failed the run-time self-check before the view's first GPU render), `device-lost`\n * (the device was lost; the rest of the view runs on the CPU) and `disposed` (the prepared view was disposed). 2.22.0 (#594):\n * `quality-code-unavailable` (the on-demand GPU full-quality code could not be loaded; that render runs the CPU reference, and\n * the next render that needs the code tries to load it again).\n */\nexport type DisplayViewGpuFallbackReason = ImageKernelFallbackReason | \"unsupported-on-backend\" | \"conformance-failed\" | \"device-lost\" | \"disposed\" |\n \"quality-code-unavailable\";\n\n/** 2.11 (#481): the run-time conformance self-check of a device, run once before the view's first GPU render. */\nexport interface DisplayViewGpuConformance {\n /** The ids of the cases run, in order (the built-in image-kernel cases, then the renderer's own). */\n cases: readonly string[];\n passed: boolean;\n /** The first case that failed, or null. */\n failedCase: string | null;\n /** What the failed case reported, or null. */\n detail: string | null;\n}\n\n/**\n * 2.11 (#481): where a display view's render ran, in the words of the image-kernel execution record (`ImageKernelExecution`):\n * `backend` names the path that ran (`cpu-reference`, the float64 engine reference, or `webgpu-f32`, a float32 approximation\n * within `errorBound`), `requestedBackend` what `gpu` asked for, and `fallbackReason` why a request for the GPU ran the CPU.\n * `adapter` describes the device's adapter whenever one was involved, also when the view then fell back; `conformance` is\n * the device's self-check once it has run. A CPU render keeps `assurance: \"engine-reference\"` and `fast: false`.\n */\nexport interface DisplayViewExecution extends Omit<ImageKernelExecution, \"fallbackReason\"> {\n /** The `gpu` option the view was prepared with. */\n gpu: DisplayViewGpuMode;\n fallbackReason: DisplayViewGpuFallbackReason | null;\n adapter: ImageKernelAdapterDescription | null;\n conformance: DisplayViewGpuConformance | null;\n /**\n * 2.11: the composite chart kernel's device probe when this render needed it (composite charts, the 2.3 elements and\n * `material-layers` scenes): the device class and the product path the kernel ran with, or, on a refusal (`fallbackReason`\n * `unsupported-on-backend`), why. Null when the render did not run the probe (the 2.0 presets, `gpu: \"off\"`).\n */\n compositeProbe: ChartCompositeProbeRecord | null;\n}\n\n/** 2.11 (#481): `diagnostics.fast` of a display view: the capture's report plus where the render ran. */\nexport interface DisplayViewFastReport extends SimulateCaptureFastReport {\n /** Where this render ran (see {@link DisplayViewExecution}). `assurance` above follows it. */\n execution: DisplayViewExecution;\n}\n\nconst CPU_LIMITATIONS = /* @__PURE__ */ Object.freeze([\"Float64 engine reference execution; results are the reference by definition\"]);\n\n/** Internal: the execution record of a display view rendered on the CPU reference. `requested` names what `gpu` asked for. */\nexport function cpuDisplayViewExecution(gpu: DisplayViewGpuMode, fallbackReason: DisplayViewGpuFallbackReason | null, adapter: ImageKernelAdapterDescription | null,\n conformance: DisplayViewGpuConformance | null, detail?: string, compositeProbe: ChartCompositeProbeRecord | null = null): DisplayViewExecution {\n const requestedBackend: ImageKernelBackend = gpu === \"off\" ? \"cpu-reference\" : \"webgpu-f32\";\n const limitations = detail === undefined ? CPU_LIMITATIONS : Object.freeze([...CPU_LIMITATIONS, \"WebGPU was requested (gpu: \\\"\" + gpu + \"\\\") and the CPU reference ran: \" + detail]);\n return Object.freeze({ gpu, backend: \"cpu-reference\", requestedBackend, fallbackReason, arithmetic: \"float64\", assurance: \"engine-reference\", fast: false,\n bitIdenticalToReference: true, errorBound: null, diagnosticsExact: true, diagnosticUncertaintySampleCount: 0, limitations, adapter, conformance, compositeProbe });\n}\n\n// ---------------------------------------------------------------------------------------------------------------\n// The renderer contract (#478 implements it; until then the only implementation is a test fake).\n\n/**\n * Internal (#481): the device a renderer or conformance case runs on. It is the engine's `WebGpuRuntime` object\n * (`src/gpu/webgpu-runtime.ts`: `device`, `guard`, `destroy` and the rest), seen here through its WebGPU-free members only so\n * that no WebGPU type reaches the published declarations (docs/WEBGPU.md); a renderer in the engine casts it to `WebGpuRuntime`.\n */\nexport interface DisplayViewGpuRuntimeHandle {\n readonly adapter: ImageKernelAdapterDescription | null;\n readonly maximumStorageBindingBytes: number;\n readonly maximumWorkgroupsPerDimension: number;\n isLost(): boolean;\n}\n\n/** What a prepared request asks of a GPU renderer (`supports`): the options that shape a render. */\nexport interface DisplayViewGpuRequest {\n ahd: boolean;\n diffraction: boolean;\n antiAliasing: boolean;\n /** Pixel-aperture samples per axis (1: centre sampling). */\n boxSamples: number;\n toneCurve: SdrToneCurve;\n /** #593, #601: true with `highlightMode: \"reconstruct\"` or `gamutHandling: \"desaturate-to-luminance\"` (coupled rendering steps). */\n coupled?: boolean;\n /**\n * #492: true when `lens.defocus` needs the defocus disc (out of focus): the expected signal then carries the disc, or each\n * node's diffraction kernel convolved with it, as site kernels (#492 step 2b), which the engine's renderer gathers in its\n * Quality site pass (step 2c). Absent or false otherwise.\n */\n defocus?: boolean;\n /**\n * #564: true when the defocus kernel's radius is above 64 sites, so the expected signal convolves it by runs on the CPU\n * (`largeKernel`); no GPU renderer takes it. Absent or false otherwise.\n */\n largeDefocus?: boolean;\n /**\n * #563: true when the request has `lens.projection`, `lens.distortion`, `lens.vignetting` or camera rotation: the CPU reference\n * renders it (display-view-lens-signal.ts) and no GPU renderer is asked or device requested (`unsupported-on-backend`).\n */\n lens?: boolean;\n /**\n * #550: true when the request has `illumination` (mixed lighting): the radiance at a point is no longer a function of its\n * material, so the GPU material lookup cannot render it; the CPU reference does, exactly, and no device is requested.\n */\n mixedIllumination?: boolean;\n /** The scene's form: an engine chart, a declared `material-layers` scene (#491), or a caller function. */\n scene: \"chart\" | \"material-layers\" | \"material-function\" | \"reflectance-function\" | \"radiance-function\" | \"image-plane\";\n}\n/** One render of a region: the CPU renderer's own setup (tables, readout, demosaic, region, callbacks) and the render's signal. */\nexport interface DisplayViewGpuPart { setup: DisplayViewSetup; signal: AbortSignal | undefined }\n/** What a GPU render returns: the CPU renderer's result shape plus the a-priori bound of its values against the reference. */\nexport interface DisplayViewGpuRenderOutput extends DisplayViewRenderResult {\n errorBound: NonNullable<ImageKernelExecution[\"errorBound\"]>;\n /** Samples whose float32 classification fell inside its bound (0 when none). */\n diagnosticUncertaintySampleCount?: number;\n /** The composite chart kernel's device probe record, when the render used the composite material module. */\n compositeProbe?: ChartCompositeProbeRecord;\n}\n/** A conformance case: returns `true` when the device agrees with the reference within the case's bound, or a sentence saying how it did not. */\nexport interface DisplayViewGpuConformanceCase { id: string; run(runtime: DisplayViewGpuRuntimeHandle, signal: AbortSignal | undefined): Promise<true | string> }\n/**\n * Internal (#481): the contract a GPU display-view renderer fulfils (#478). One instance serves one device, created by the\n * registered factory for each prepared view that acquires or shares a device. `supports` says whether the renderer covers a\n * prepared request (`true`) or why not (a sentence; the view then runs the CPU reference labelled `unsupported-on-backend`).\n * `render` renders one region on the device and must throw `ImageKernelExecutionError` with reason `device-lost` or `aborted`\n * for those two events, as the accelerator's operations do; a render that throws `unsupported-on-backend` (a request the\n * renderer finds it does not cover only when rendering) runs the CPU reference labelled with that reason, or fails with it under\n * `\"require\"`. `conformanceCases` are run after the built-in image-kernel cases before the device's first render; a failure keeps\n * the whole view on the CPU. #594: `onDemandConformanceCases` returns the cases a render needs beyond those (code the renderer\n * loads on demand, such as the Quality kernels), or null; they run once, before the first render that returns them, and their\n * ids are appended to the conformance record; a failure keeps that render and every later one on the CPU. `dispose` releases\n * what the renderer holds on the device (#491: uploaded scene records); the session calls it when the prepared view is disposed.\n */\nexport interface DisplayViewGpuRenderer {\n readonly id: string;\n supports(request: DisplayViewGpuRequest): true | string;\n render(part: DisplayViewGpuPart): Promise<DisplayViewGpuRenderOutput>;\n readonly conformanceCases?: readonly DisplayViewGpuConformanceCase[];\n onDemandConformanceCases?(setup: DisplayViewSetup): Promise<readonly DisplayViewGpuConformanceCase[]> | null;\n dispose?(): void;\n}\nexport type DisplayViewGpuRendererFactory = (runtime: DisplayViewGpuRuntimeHandle) => DisplayViewGpuRenderer;\n\nlet rendererFactory: DisplayViewGpuRendererFactory | null = null;\n/**\n * Internal (#481): registers the renderer that `prepareDisplayView` uses for `gpu: \"auto\" | \"require\"`, and returns the one\n * registered before (null: none). #478's renderer registers itself here; tests register a fake. With none registered no device\n * is requested and every GPU request falls back (or fails) with `unsupported-on-backend`.\n */\nexport function setDisplayViewGpuRendererFactory(factory: DisplayViewGpuRendererFactory | null): DisplayViewGpuRendererFactory | null {\n if (factory !== null && typeof factory !== \"function\") throw new InvalidConfigurationError(\"setDisplayViewGpuRendererFactory expects a function or null.\");\n const previous = rendererFactory;\n rendererFactory = factory;\n return previous;\n}\n/** Internal: the registered factory. */\nexport function displayViewGpuRendererFactory(): DisplayViewGpuRendererFactory | null { return rendererFactory; }\n"]}
@@ -0,0 +1,15 @@
1
+ /** Beyond this many standard deviations from a clip level the clip changes the moments by less than 1e-15 of σ². */
2
+ export declare const CLIP_REACH_SIGMA = 8.5;
3
+ /** Standard normal density. */
4
+ export declare function phi(z: number): number;
5
+ /**
6
+ * Standard normal distribution function, Φ(z) = 1 − Q(z), with Q from the rational approximation 26.2.17 of
7
+ * Abramowitz & Stegun, Handbook of Mathematical Functions (NBS AMS 55, 1964; free, US government work):
8
+ * absolute error below 7.5e-8.
9
+ */
10
+ export declare function bigPhi(z: number): number;
11
+ /** Gauss–Legendre nodes and weights on [−1, 1], 16 points (computed once by Newton iteration on P_16 from cos(π(i + ¾)/(n + ½))). */
12
+ export declare const GL: {
13
+ x: Float64Array;
14
+ w: Float64Array;
15
+ };
@@ -0,0 +1,44 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ /**
3
+ * The display view's normal-distribution helpers (shared by the default path, display-view.ts, and the on-demand coupled
4
+ * rendering steps, display-view-rendering.ts, which must not be imported statically by the default path).
5
+ */
6
+ import { portableCosTwoPi, portableExp } from "../core/portable-math.js";
7
+ /** Beyond this many standard deviations from a clip level the clip changes the moments by less than 1e-15 of σ². */
8
+ export const CLIP_REACH_SIGMA = 8.5;
9
+ /** Standard normal density. */
10
+ export function phi(z) { return 0.3989422804014327 * portableExp(-0.5 * z * z); }
11
+ /**
12
+ * Standard normal distribution function, Φ(z) = 1 − Q(z), with Q from the rational approximation 26.2.17 of
13
+ * Abramowitz & Stegun, Handbook of Mathematical Functions (NBS AMS 55, 1964; free, US government work):
14
+ * absolute error below 7.5e-8.
15
+ */
16
+ export function bigPhi(z) {
17
+ const x = Math.abs(z), t = 1 / (1 + 0.2316419 * x);
18
+ const q = phi(x) * t * (0.319381530 + t * (-0.356563782 + t * (1.781477937 + t * (-1.821255978 + t * 1.330274429))));
19
+ return z >= 0 ? 1 - q : q;
20
+ }
21
+ /** Gauss–Legendre nodes and weights on [−1, 1], 16 points (computed once by Newton iteration on P_16 from cos(π(i + ¾)/(n + ½))). */
22
+ export const GL = /* @__PURE__ */ (() => {
23
+ const n = 16, x = new Float64Array(n), w = new Float64Array(n);
24
+ for (let i = 0; i < n; i++) {
25
+ let z = portableCosTwoPi((i + 0.75) / (2 * n + 1)), dp = 0;
26
+ for (let it = 0; it < 100; it++) {
27
+ let p0 = 1, p1 = z;
28
+ for (let k = 2; k <= n; k++) {
29
+ const p2 = ((2 * k - 1) * z * p1 - (k - 1) * p0) / k;
30
+ p0 = p1;
31
+ p1 = p2;
32
+ }
33
+ dp = n * (z * p1 - p0) / (z * z - 1);
34
+ const dz = p1 / dp;
35
+ z -= dz;
36
+ if (Math.abs(dz) < 1e-16)
37
+ break;
38
+ }
39
+ x[i] = z;
40
+ w[i] = 2 / ((1 - z * z) * dp * dp);
41
+ }
42
+ return { x, w };
43
+ })();
44
+ //# sourceMappingURL=display-view-normal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"display-view-normal.js","sourceRoot":"","sources":["../../src/facade/display-view-normal.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEzE,oHAAoH;AACpH,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,CAAC;AACpC,+BAA+B;AAC/B,MAAM,UAAU,GAAG,CAAC,CAAS,IAAY,OAAO,kBAAkB,GAAG,WAAW,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACjG;;;;GAIG;AACH,MAAM,UAAU,MAAM,CAAC,CAAS;IAC9B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,SAAS,GAAG,CAAC,CAAC,CAAC;IACnD,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,GAAG,CAAC,GAAG,CAAC,CAAC,WAAW,GAAG,CAAC,GAAG,CAAC,WAAW,GAAG,CAAC,GAAG,CAAC,CAAC,WAAW,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IACrH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5B,CAAC;AACD,qIAAqI;AACrI,MAAM,CAAC,MAAM,EAAE,GAAG,eAAe,CAAC,CAAC,GAAyC,EAAE;IAC5E,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC;IAC/D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,IAAI,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC3D,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC;YAChC,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;gBAAC,EAAE,GAAG,EAAE,CAAC;gBAAC,EAAE,GAAG,EAAE,CAAC;YAAC,CAAC;YACxG,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YACrC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;YACnB,CAAC,IAAI,EAAE,CAAC;YACR,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK;gBAAE,MAAM;QAClC,CAAC;QACD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AAClB,CAAC,CAAC,EAAE,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * The display view's normal-distribution helpers (shared by the default path, display-view.ts, and the on-demand coupled\n * rendering steps, display-view-rendering.ts, which must not be imported statically by the default path).\n */\n\nimport { portableCosTwoPi, portableExp } from \"../core/portable-math.js\";\n\n/** Beyond this many standard deviations from a clip level the clip changes the moments by less than 1e-15 of σ². */\nexport const CLIP_REACH_SIGMA = 8.5;\n/** Standard normal density. */\nexport function phi(z: number): number { return 0.3989422804014327 * portableExp(-0.5 * z * z); }\n/**\n * Standard normal distribution function, Φ(z) = 1 − Q(z), with Q from the rational approximation 26.2.17 of\n * Abramowitz & Stegun, Handbook of Mathematical Functions (NBS AMS 55, 1964; free, US government work):\n * absolute error below 7.5e-8.\n */\nexport function bigPhi(z: number): number {\n const x = Math.abs(z), t = 1 / (1 + 0.2316419 * x);\n const q = phi(x) * t * (0.319381530 + t * (-0.356563782 + t * (1.781477937 + t * (-1.821255978 + t * 1.330274429))));\n return z >= 0 ? 1 - q : q;\n}\n/** Gauss–Legendre nodes and weights on [−1, 1], 16 points (computed once by Newton iteration on P_16 from cos(π(i + ¾)/(n + ½))). */\nexport const GL = /* @__PURE__ */ ((): { x: Float64Array; w: Float64Array } => {\n const n = 16, x = new Float64Array(n), w = new Float64Array(n);\n for (let i = 0; i < n; i++) {\n let z = portableCosTwoPi((i + 0.75) / (2 * n + 1)), dp = 0;\n for (let it = 0; it < 100; it++) {\n let p0 = 1, p1 = z;\n for (let k = 2; k <= n; k++) { const p2 = ((2 * k - 1) * z * p1 - (k - 1) * p0) / k; p0 = p1; p1 = p2; }\n dp = n * (z * p1 - p0) / (z * z - 1);\n const dz = p1 / dp;\n z -= dz;\n if (Math.abs(dz) < 1e-16) break;\n }\n x[i] = z; w[i] = 2 / ((1 - z * z) * dp * dp);\n }\n return { x, w };\n})();\n\n"]}
@@ -0,0 +1,102 @@
1
+ import { type SdrToneCurve, type SdrToneCurveParameters } from "../output/sdr-rendering.js";
2
+ import type { DisplayViewSetup } from "./display-view.js";
3
+ /**
4
+ * Internal (exported for tests). The n-point Gauss–Hermite rule of the standard normal: Σ w_i f(x_i) ≈ E[f(Z)], Z ~ N(0, 1).
5
+ * The nodes are the eigenvalues of the Jacobi matrix of the orthonormal Hermite polynomials (zero diagonal, off-diagonal √k),
6
+ * found by Sturm-sequence bisection, and w_i = 1/Σ_k p_k(x_i)² (Golub & Welsch 1969). Only correctly rounded operations, so the
7
+ * rule has the same bits in every JavaScript engine.
8
+ */
9
+ export declare function gaussHermite(n: number): {
10
+ x: Float64Array;
11
+ w: Float64Array;
12
+ };
13
+ /** Points per axis of the 3-D rule (full and fast) and of the fast 1-D luminance rule. */
14
+ export declare const DISPLAY_VIEW_CHAIN_POINTS: Readonly<{
15
+ full: 16;
16
+ fast: 6;
17
+ }>;
18
+ export declare const DISPLAY_VIEW_LUMINANCE_FAST_POINTS = 8;
19
+ /** What the view renders: the request's tone curve, highlight mode and gamut handling (#601), and whether the fast rules run. */
20
+ export interface DisplayViewRenderingChoice {
21
+ toneCurve: SdrToneCurve;
22
+ toneCurveParameters?: SdrToneCurveParameters;
23
+ /** #602: "reconstruct-neighbors" rebuilds clipped channels from the ratios around each clipped region (src/color/neighbor-highlight-reconstruction.ts). */
24
+ highlightMode: "clip" | "reconstruct" | "reconstruct-neighbors";
25
+ gamutHandling: "clip-components" | "desaturate-to-luminance";
26
+ fast: boolean;
27
+ }
28
+ /** The coupled steps of one view (see the module notes), or null for a view without them (its arithmetic is unchanged). */
29
+ export interface DisplayViewCoupledRendering {
30
+ readonly luminanceTone: boolean;
31
+ /** True with either reconstruct mode (the highlight step couples the channels). */
32
+ readonly reconstruct: boolean;
33
+ /** #602: the neighbor reconstruction (its pixels take their region's ratios, `bindView` and `at`). */
34
+ readonly neighbors: boolean;
35
+ /**
36
+ * #602: binds a render's expected (noise-free) camera channels, from which the clipped regions and their ratios are found on
37
+ * demand, and returns the counters of the regions it measured.
38
+ */
39
+ bindView?(setup: DisplayViewSetup): void;
40
+ /** #602: the real pixel (native site coordinates) whose moments `chain` computes next. */
41
+ at?(x: number, y: number): void;
42
+ /**
43
+ * #605: the ratios ρ that `chain` uses at real pixel (x, y) (as `at` selects them) into out, or −1 in out[0] where the pixel
44
+ * takes none (the highlight step then keeps u): the GPU kernels read them from the host.
45
+ */
46
+ ratioAt?(x: number, y: number, out: Float64Array): void;
47
+ /** #602: regions measured, and regions whose search stopped at the size cap (their ratios from the part found). */
48
+ readonly neighborRegions: {
49
+ measured: number;
50
+ capped: number;
51
+ };
52
+ readonly desaturate: boolean;
53
+ readonly choice: DisplayViewRenderingChoice;
54
+ /** Points per axis of the 3-D rule in use; the luminance rule's Gauss–Hermite nodes and weights (8 points), for the GPU kernels. */
55
+ readonly chainPoints: number;
56
+ readonly chainRule: {
57
+ x: Float64Array;
58
+ w: Float64Array;
59
+ };
60
+ readonly luminanceRule: {
61
+ x: Float64Array;
62
+ w: Float64Array;
63
+ };
64
+ /** The luminance curve's ratio limit r(0+) (1, 0, 1/(σ·g(Lw)) or ∞). */
65
+ readonly ratioAtZero: number;
66
+ /** Renders one deterministic camera pixel (WB, highlight, matrix, tone, gamut, clip) into out (the AHD correction's pixels). */
67
+ pixel(c0: number, c1: number, c2: number, out: Float64Array): void;
68
+ /**
69
+ * The moments of the rendered pixel for camera channels c ~ N(cm, C) (C row-major 3 × 3), integrated over the whole chain:
70
+ * mean (hm), variance (hv) and the expected slopes ∂out_k/∂c_j (A, row-major 3 × 3). Returns the number of nodes evaluated.
71
+ */
72
+ chain(cm: Float64Array, C: Float64Array, hm: Float64Array, hv: Float64Array, A: Float64Array): number;
73
+ /**
74
+ * Whether the reconstruct blend is within reach of channels c ~ N(cm, C): some channel's mean + 8.5σ above the blend's start.
75
+ * Out of reach the highlight step is the unclipped white balance.
76
+ */
77
+ reconstructInReach(cm: Float64Array, C: Float64Array): boolean;
78
+ /**
79
+ * The luminance tone curve on developed values y ~ N(μ, Σ) (Σ row-major 3 × 3): mean (hm), variance (hv) and the expected
80
+ * slopes J = E[∂out/∂y] (row-major). Returns false when a component reaches 1 within reach and the desaturation is on (the
81
+ * caller then integrates the chain), else true.
82
+ */
83
+ tone(mu: Float64Array, S: Float64Array, hm: Float64Array, hv: Float64Array, J: Float64Array): boolean;
84
+ }
85
+ /** #602: a render's noise-free camera channels at a real pixel (native coordinates), and the output raster's native bounds. */
86
+ export interface NeighborView {
87
+ channels(x: number, y: number, out: Float64Array): void;
88
+ x0: number;
89
+ y0: number;
90
+ width: number;
91
+ height: number;
92
+ }
93
+ /** #602: the most pixels a clipped region's search visits (fast and full); a larger region takes its ratios from the part found. */
94
+ export declare const DISPLAY_VIEW_NEIGHBOR_REGION_LIMIT: Readonly<{
95
+ fast: number;
96
+ full: number;
97
+ }>;
98
+ /**
99
+ * Internal: the coupled rendering of a view, or null when its tone curve is per channel, its highlight mode `clip` and its gamut
100
+ * handling the component clip (the view's own per-component arithmetic then runs, byte for byte as before).
101
+ */
102
+ export declare function createDisplayViewCoupledRendering(choice: DisplayViewRenderingChoice, gains: readonly number[], clipLevel: number, matrix: readonly (readonly number[])[]): DisplayViewCoupledRendering | null;