@photivra/engine 2.9.0 → 2.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +223 -1
- package/CITATION.cff +1 -1
- package/NODE_SUPPORT.md +21 -3
- package/README.md +6 -6
- package/SECURITY.md +1 -1
- package/THIRD_PARTY.md +2 -0
- package/dist/capture/native-environment-lean.js +89 -5
- package/dist/capture/native-environment-lean.js.map +1 -1
- package/dist/capture/native-environment-tabulated.d.ts +37 -0
- package/dist/capture/native-environment-tabulated.js +42 -6
- package/dist/capture/native-environment-tabulated.js.map +1 -1
- package/dist/core/portable-math.d.ts +19 -0
- package/dist/core/portable-math.js +82 -0
- package/dist/core/portable-math.js.map +1 -1
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/dist/core/version.js.map +1 -1
- package/dist/facade/channel-response.d.ts +15 -0
- package/dist/facade/channel-response.js +33 -0
- package/dist/facade/channel-response.js.map +1 -0
- package/dist/facade/chart-material-layers.d.ts +115 -0
- package/dist/facade/chart-material-layers.js +224 -0
- package/dist/facade/chart-material-layers.js.map +1 -0
- package/dist/facade/chart-radiance-batch.d.ts +8 -2
- package/dist/facade/chart-radiance-batch.js +11 -4
- package/dist/facade/chart-radiance-batch.js.map +1 -1
- package/dist/facade/chart-scenes.d.ts +134 -0
- package/dist/facade/chart-scenes.js +32 -22
- package/dist/facade/chart-scenes.js.map +1 -1
- package/dist/facade/diffraction-provider.d.ts +8 -2
- package/dist/facade/diffraction-provider.js +120 -16
- package/dist/facade/diffraction-provider.js.map +1 -1
- package/dist/facade/display-view-gpu-session.d.ts +18 -0
- package/dist/facade/display-view-gpu-session.js +280 -0
- package/dist/facade/display-view-gpu-session.js.map +1 -0
- package/dist/facade/display-view-gpu.d.ts +146 -0
- package/dist/facade/display-view-gpu.js +59 -0
- package/dist/facade/display-view-gpu.js.map +1 -0
- package/dist/facade/display-view.d.ts +123 -1
- package/dist/facade/display-view.js +478 -116
- package/dist/facade/display-view.js.map +1 -1
- package/dist/facade/expected-signal-setup.d.ts +5 -0
- package/dist/facade/expected-signal-setup.js +18 -1
- package/dist/facade/expected-signal-setup.js.map +1 -1
- package/dist/facade/expected-signal.d.ts +80 -6
- package/dist/facade/expected-signal.js +200 -24
- package/dist/facade/expected-signal.js.map +1 -1
- package/dist/facade/scene-radiance.d.ts +4 -2
- package/dist/facade/scene-radiance.js +7 -4
- package/dist/facade/scene-radiance.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +81 -7
- package/dist/facade/simulate-capture.js +276 -53
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/facade/simulate-display-view.d.ts +54 -3
- package/dist/facade/simulate-display-view.js +120 -27
- package/dist/facade/simulate-display-view.js.map +1 -1
- package/dist/gpu/chart-composite-gpu.d.ts +119 -0
- package/dist/gpu/chart-composite-gpu.js +572 -0
- package/dist/gpu/chart-composite-gpu.js.map +1 -0
- package/dist/gpu/chart-radiance-gpu.d.ts +6 -6
- package/dist/gpu/chart-radiance-gpu.js +9 -11
- package/dist/gpu/chart-radiance-gpu.js.map +1 -1
- package/dist/gpu/display-view-chart-material-module.d.ts +10 -0
- package/dist/gpu/display-view-chart-material-module.js +58 -0
- package/dist/gpu/display-view-chart-material-module.js.map +1 -0
- package/dist/gpu/display-view-composite-material-module.d.ts +68 -0
- package/dist/gpu/display-view-composite-material-module.js +248 -0
- package/dist/gpu/display-view-composite-material-module.js.map +1 -0
- package/dist/gpu/display-view-quality-gpu.d.ts +185 -0
- package/dist/gpu/display-view-quality-gpu.js +1000 -0
- package/dist/gpu/display-view-quality-gpu.js.map +1 -0
- package/dist/gpu/display-view-speed-gpu.d.ts +156 -0
- package/dist/gpu/display-view-speed-gpu.js +524 -0
- package/dist/gpu/display-view-speed-gpu.js.map +1 -0
- package/dist/gpu/image-kernel-accelerator.d.ts +23 -4
- package/dist/gpu/image-kernel-accelerator.js +58 -10
- package/dist/gpu/image-kernel-accelerator.js.map +1 -1
- package/dist/gpu/image-kernel-execution.d.ts +60 -3
- package/dist/gpu/image-kernel-execution.js +2 -2
- package/dist/gpu/image-kernel-execution.js.map +1 -1
- package/dist/gpu/sensor-stage-gpu.d.ts +11 -0
- package/dist/gpu/sensor-stage-gpu.js +42 -13
- package/dist/gpu/sensor-stage-gpu.js.map +1 -1
- package/dist/gpu/webgpu-runtime.d.ts +4 -2
- package/dist/gpu/webgpu-runtime.js +13 -4
- package/dist/gpu/webgpu-runtime.js.map +1 -1
- package/dist/gpu/webgpu-switch.d.ts +4 -0
- package/dist/gpu/webgpu-switch.js +29 -0
- package/dist/gpu/webgpu-switch.js.map +1 -0
- package/dist/gpu/wgsl-chart-composite-kernel.d.ts +52 -0
- package/dist/gpu/wgsl-chart-composite-kernel.js +515 -0
- package/dist/gpu/wgsl-chart-composite-kernel.js.map +1 -0
- package/dist/gpu/wgsl-chart-kernel.d.ts +11 -9
- package/dist/gpu/wgsl-chart-kernel.js +33 -27
- package/dist/gpu/wgsl-chart-kernel.js.map +1 -1
- package/dist/gpu/wgsl-display-view-quality-kernel.d.ts +95 -0
- package/dist/gpu/wgsl-display-view-quality-kernel.js +769 -0
- package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -0
- package/dist/gpu/wgsl-display-view-speed-kernel.d.ts +75 -0
- package/dist/gpu/wgsl-display-view-speed-kernel.js +386 -0
- package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -0
- package/dist/gpu/wgsl-sensor-kernel.d.ts +28 -9
- package/dist/gpu/wgsl-sensor-kernel.js +94 -50
- package/dist/gpu/wgsl-sensor-kernel.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/optics/defocus-disc-kernel.d.ts +61 -0
- package/dist/optics/defocus-disc-kernel.js +191 -0
- package/dist/optics/defocus-disc-kernel.js.map +1 -0
- package/dist/optics/irradiance-convolution.d.ts +11 -0
- package/dist/optics/irradiance-convolution.js +64 -24
- package/dist/optics/irradiance-convolution.js.map +1 -1
- package/dist/optics/scene-to-sensor-irradiance.d.ts +13 -0
- package/dist/optics/scene-to-sensor-irradiance.js +58 -24
- package/dist/optics/scene-to-sensor-irradiance.js.map +1 -1
- package/dist/optics/sensor-aperture-rays.js +2 -1
- package/dist/optics/sensor-aperture-rays.js.map +1 -1
- package/dist/optics/sensor-environment-query.js +4 -3
- package/dist/optics/sensor-environment-query.js.map +1 -1
- package/dist/optics/site-diffraction-kernel.d.ts +16 -0
- package/dist/optics/site-diffraction-kernel.js +60 -8
- package/dist/optics/site-diffraction-kernel.js.map +1 -1
- package/dist/processing/demosaic.js +114 -37
- package/dist/processing/demosaic.js.map +1 -1
- package/dist/schema/scene-radiance.d.ts +8 -0
- package/dist/schema/scene-radiance.js +28 -17
- package/dist/schema/scene-radiance.js.map +1 -1
- package/dist/sensor/environment-photo-signal.d.ts +21 -0
- package/dist/sensor/environment-photo-signal.js +68 -2
- package/dist/sensor/environment-photo-signal.js.map +1 -1
- package/docs/API_REFERENCE.md +60 -1
- package/docs/QUICK_START.md +120 -11
- package/docs/USAGE.md +82 -2
- package/docs/api/core-version.md +1 -1
- package/docs/api/exports.json +157 -2
- package/docs/api/facade-chart-material-layers.md +137 -0
- package/docs/api/facade-chart-radiance-batch.md +7 -2
- package/docs/api/facade-display-view-gpu.md +94 -0
- package/docs/api/facade-display-view.md +50 -0
- package/docs/api/facade-scene-radiance.md +3 -2
- package/docs/api/facade-simulate-capture.md +81 -12
- package/docs/api/facade-simulate-display-view.md +39 -2
- package/docs/api/gpu-image-kernel-accelerator.md +10 -3
- package/docs/api/gpu-image-kernel-execution.md +76 -4
- package/docs/api/gpu-webgpu-switch.md +23 -0
- package/package.json +3 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-kernel-execution.js","sourceRoot":"","sources":["../../src/gpu/image-kernel-execution.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Execution-backend labels, error bounds and domain errors for the optional image-kernel accelerator.\n *\n * `cpu-reference` is the float64 engine reference and the default. `webgpu-f32` is a separate float32\n * approximation backend. Every one of its results carries a forward-error bound worked out in advance\n * from:\n * - IEEE 754 binary32 rounding (unit roundoff u = 2^-24; γ_k = k·u/(1 − k·u), the classical factor\n * in error bounds for floating-point sums and inner products: Rump & Jeannerod, SIAM J. Matrix\n * Anal. Appl. 35(2), 2014, sec. 1, free author copy. Also see: Higham, Accuracy and Stability of\n * Numerical Algorithms, 2nd ed., SIAM 2002, §2–§3);\n * - the WGSL built-in accuracy table (W3C WebGPU Shading Language, §\"Floating Point Accuracy\").\n * See docs/WEBGPU.md.\n */\n\nimport { requireInputObject } from \"../core/record-validation.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\n\n/** Requested or actual execution backend. */\nexport type ImageKernelBackend = \"cpu-reference\" | \"webgpu-f32\";\n\n/** Why a requested WebGPU backend was not used (only with `fallback: \"cpu-reference\"`). */\nexport type ImageKernelFallbackReason = \"webgpu-unavailable\" | \"adapter-unavailable\" | \"device-request-failed\" |\n \"insufficient-limits\" | \"unsupported-platform-endianness\";\n\n/** Failure classes reported by {@link ImageKernelExecutionError}. */\nexport type ImageKernelFailureReason = ImageKernelFallbackReason | \"device-lost\" | \"out-of-memory\" | \"gpu-validation\" |\n \"aborted\" | \"disposed\" | \"busy\" | \"unsupported-on-backend\" | \"unsupported-float32-domain\" | \"indeterminate-float32-classification\";\n\n/** Domain error for getting and running a backend. Input validation still throws the engine's existing errors. */\nexport class ImageKernelExecutionError extends Error {\n readonly code = \"IMAGE_KERNEL_EXECUTION\";\n readonly reason: ImageKernelFailureReason;\n\n constructor(reason: ImageKernelFailureReason, message: string) {\n super(message);\n this.name = \"ImageKernelExecutionError\";\n this.reason = reason;\n }\n}\n\n/** Integer output codes: |code_webgpu − code_reference| ≤ maximumAbsoluteCodeDifference for every sample. */\nexport interface ImageKernelCodeErrorBound {\n kind: \"integer-code-difference\";\n maximumAbsoluteCodeDifference: number;\n /** Bound on the float32 linear value entering the sRGB transfer, after tone and gamut handling. */\n linearAbsoluteBound: number;\n /** Declared bound on the WGSL sRGB transfer evaluation (pow), see WEBGPU_F32_TRANSFER_ABSOLUTE_BOUND. */\n transferAbsoluteBound: number;\n}\n\n/** Non-negative linear sums: |v_webgpu − v_reference| ≤ relative·v_reference + absolute for every sample. */\nexport interface ImageKernelRelativeErrorBound {\n kind: \"relative-to-reference\";\n relative: number;\n absolute: number;\n}\n\n/**\n * Seeded stochastic stages (the sensor stage). Random states are integer arithmetic and bit-identical to\n * the reference. A site is flagged when any float32 decision (sampling test, saturation limit, rounding)\n * fell inside its a-priori bound. Every unflagged site has exactly the reference code and flags; only\n * flagged sites may differ, and the statistical-equivalence tests cover them (docs/WEBGPU.md).\n */\nexport interface ImageKernelSeededRealizationBound {\n kind: \"exact-except-flagged-sites\";\n /** Number of flagged sites; equal to the execution's `diagnosticUncertaintySampleCount`. */\n flaggedSiteCount: number;\n noiseModel: { id: string; version: string };\n seedSchedule: string;\n}\n\n/** Label attached to every accelerated result. */\nexport interface ImageKernelExecution {\n backend: ImageKernelBackend;\n requestedBackend: ImageKernelBackend;\n fallbackReason: ImageKernelFallbackReason | null;\n arithmetic: \"float64\" | \"float32\";\n assurance: \"engine-reference\" | \"approximation-with-a-priori-bound\";\n /**\n * True only for `cpu-reference`. Bit-exact identities (SHA-256 artifact bindings, byte-parity fixtures,\n * cross-engine determinism hashes) are CPU-only and must never be computed from a `webgpu-f32` result.\n */\n bitIdenticalToReference: boolean;\n errorBound: ImageKernelCodeErrorBound | ImageKernelRelativeErrorBound | ImageKernelSeededRealizationBound | null;\n /**\n * Diagnostic counts equal the reference when no sample fell inside a float32 classification band\n * (`diagnosticUncertaintySampleCount === 0`). Otherwise each count differs by at most that many\n * samples.\n */\n diagnosticsExact: boolean;\n diagnosticUncertaintySampleCount: number;\n limitations: readonly string[];\n}\n\n/** IEEE 754 binary32 unit roundoff. */\nexport const WEBGPU_F32_UNIT_ROUNDOFF = 2 ** -24;\n/**\n * Declared absolute error bound for the WGSL sRGB encode on [0, 1]: `1.055·pow(x, 1/2.4) − 0.055`. pow\n * takes its accuracy from exp2(y·log2 x) (log2: 3 ULP, or 2^-21 absolute on [0.5, 2]; exp2: 3 + 2|x|\n * ULP). The worst case over [0.0031308, 1] is about 2.5e-6. The bound 2^-17 ≈ 7.6e-6 keeps a 3× margin,\n * and also covers the small jump where the sRGB segments join (< 1e-7).\n */\nexport const WEBGPU_F32_TRANSFER_ABSOLUTE_BOUND = 2 ** -17;\n/** Largest slope of the sRGB encode on [0, 1] (the linear segment, 12.92). */\nexport const SRGB_ENCODE_LIPSCHITZ = 12.92;\n\n/** Higham's γ_k for binary32. */\nexport function float32Gamma(k: number): number {\n const ku = k * WEBGPU_F32_UNIT_ROUNDOFF;\n return ku < 1 ? ku / (1 - ku) : Number.POSITIVE_INFINITY;\n}\n\n/** Integer-code bound from a bound on the linear value: |Δcode| ≤ ⌊maximum·(12.92·δ_L + δ_E)⌋ + 1, capped at maximum. */\nexport function integerCodeBound(maximum: number, linearAbsoluteBound: number): ImageKernelCodeErrorBound {\n const linear = Math.min(1, linearAbsoluteBound);\n const real = maximum * (SRGB_ENCODE_LIPSCHITZ * linear + WEBGPU_F32_TRANSFER_ABSOLUTE_BOUND);\n return { kind: \"integer-code-difference\", maximumAbsoluteCodeDifference: Math.min(maximum, Math.floor(real) + 1),\n linearAbsoluteBound: linear, transferAbsoluteBound: WEBGPU_F32_TRANSFER_ABSOLUTE_BOUND };\n}\n\n/**\n * Composes two `relative-to-reference` bounds through a pipeline `second ∘ first`, where the second\n * stage is linear with non-negative weights summing to at most `secondWeightSum` per output (convolution,\n * temporal sums). With |ã − a| ≤ r₁a + a₁ elementwise and |B̃x − Bx| ≤ r₂Bx + a₂:\n * |B̃ã − Ba| ≤ |B̃ã − Bã| + |B(ã − a)| ≤ r₂(1 + r₁)Ba + r₂W·a₁ + a₂ + r₁Ba + W·a₁,\n * so r = r₁ + r₂ + r₁r₂ and a = a₂ + W·a₁·(1 + r₂). See docs/WEBGPU.md, \"Accuracy contract\".\n */\nexport function composeRelativeErrorBounds(first: ImageKernelRelativeErrorBound, second: ImageKernelRelativeErrorBound,\n secondWeightSum: number): ImageKernelRelativeErrorBound {\n requireInputObject(first, \"composeRelativeErrorBounds first bound\");\n requireInputObject(second, \"composeRelativeErrorBounds second bound\");\n for (const v of [first.relative, first.absolute, second.relative, second.absolute, secondWeightSum]) {\n if (!(typeof v === \"number\" && v >= 0 && v <= Number.MAX_VALUE)) {\n throw new InvalidScientificInputError(\"Error bounds and weight sums must be finite and non-negative.\");\n }\n }\n return { kind: \"relative-to-reference\", relative: first.relative + second.relative + first.relative * second.relative,\n absolute: second.absolute + secondWeightSum * first.absolute * (1 + second.relative) };\n}\n\nexport const CPU_REFERENCE_LIMITATIONS = Object.freeze([\"Float64 engine reference execution; results are the reference by definition\"]);\nexport const WEBGPU_F32_LIMITATIONS = Object.freeze([\n \"Float32 WebGPU execution is an approximation of the float64 reference within the reported a-priori bound\",\n \"Not bit-identical to the reference: never use for SHA-256 artifact identities, byte-parity evidence or determinism hashes\",\n \"Bound assumes a conforming WebGPU implementation (correctly rounded f32 add/multiply/divide, WGSL accuracy table)\",\n \"Execution speed depends on the adapter; software adapters do not represent GPU performance\"\n]);\n\nexport function cpuExecution(requestedBackend: ImageKernelBackend, fallbackReason: ImageKernelFallbackReason | null): ImageKernelExecution {\n return { backend: \"cpu-reference\", requestedBackend, fallbackReason, arithmetic: \"float64\", assurance: \"engine-reference\",\n bitIdenticalToReference: true, errorBound: null, diagnosticsExact: true, diagnosticUncertaintySampleCount: 0, limitations: CPU_REFERENCE_LIMITATIONS };\n}\n\nexport function webGpuExecution(errorBound: ImageKernelExecution[\"errorBound\"], uncertainty: number): ImageKernelExecution {\n return { backend: \"webgpu-f32\", requestedBackend: \"webgpu-f32\", fallbackReason: null, arithmetic: \"float32\",\n assurance: \"approximation-with-a-priori-bound\", bitIdenticalToReference: false, errorBound, diagnosticsExact: uncertainty === 0,\n diagnosticUncertaintySampleCount: uncertainty, limitations: WEBGPU_F32_LIMITATIONS };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"image-kernel-execution.js","sourceRoot":"","sources":["../../src/gpu/image-kernel-execution.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Execution-backend labels, error bounds and domain errors for the optional image-kernel accelerator.\n *\n * `cpu-reference` is the float64 engine reference and the default. `webgpu-f32` is a separate float32\n * approximation backend. Every one of its results carries a forward-error bound worked out in advance\n * from:\n * - IEEE 754 binary32 rounding (unit roundoff u = 2^-24; γ_k = k·u/(1 − k·u), the classical factor\n * in error bounds for floating-point sums and inner products: Rump & Jeannerod, SIAM J. Matrix\n * Anal. Appl. 35(2), 2014, sec. 1, free author copy. Also see: Higham, Accuracy and Stability of\n * Numerical Algorithms, 2nd ed., SIAM 2002, §2–§3);\n * - the WGSL built-in accuracy table (W3C WebGPU Shading Language, §\"Floating Point Accuracy\").\n * See docs/WEBGPU.md.\n */\n\nimport { requireInputObject } from \"../core/record-validation.js\";\nimport { InvalidScientificInputError } from \"../core/validation.js\";\n\n/** Requested or actual execution backend. */\nexport type ImageKernelBackend = \"cpu-reference\" | \"webgpu-f32\";\n\n/** Why a requested WebGPU backend was not used (only with `fallback: \"cpu-reference\"`). */\n/** Why a requested `webgpu-f32` backend ran the CPU reference instead. `webgpu-disabled`: `setWebGpuEnabled(false)` in this realm. */\nexport type ImageKernelFallbackReason = \"webgpu-unavailable\" | \"webgpu-disabled\" | \"adapter-unavailable\" | \"device-request-failed\" |\n \"insufficient-limits\" | \"unsupported-platform-endianness\";\n\n/**\n * Failure classes reported by {@link ImageKernelExecutionError}. `conformance-failed` (#481): a device failed the display view's\n * run-time self-check with `gpu: \"require\"`.\n */\nexport type ImageKernelFailureReason = ImageKernelFallbackReason | \"device-lost\" | \"out-of-memory\" | \"gpu-validation\" |\n \"aborted\" | \"disposed\" | \"busy\" | \"unsupported-on-backend\" | \"unsupported-float32-domain\" | \"indeterminate-float32-classification\" | \"conformance-failed\";\n\n/** Domain error for getting and running a backend. Input validation still throws the engine's existing errors. */\nexport class ImageKernelExecutionError extends Error {\n readonly code = \"IMAGE_KERNEL_EXECUTION\";\n readonly reason: ImageKernelFailureReason;\n\n constructor(reason: ImageKernelFailureReason, message: string) {\n super(message);\n this.name = \"ImageKernelExecutionError\";\n this.reason = reason;\n }\n}\n\n/** Integer output codes: |code_webgpu − code_reference| ≤ maximumAbsoluteCodeDifference for every sample. */\nexport interface ImageKernelCodeErrorBound {\n kind: \"integer-code-difference\";\n maximumAbsoluteCodeDifference: number;\n /** Bound on the float32 linear value entering the sRGB transfer, after tone and gamut handling. */\n linearAbsoluteBound: number;\n /** Declared bound on the WGSL sRGB transfer evaluation (pow), see WEBGPU_F32_TRANSFER_ABSOLUTE_BOUND. */\n transferAbsoluteBound: number;\n}\n\n/** Non-negative linear sums: |v_webgpu − v_reference| ≤ relative·v_reference + absolute for every sample. */\nexport interface ImageKernelRelativeErrorBound {\n kind: \"relative-to-reference\";\n relative: number;\n absolute: number;\n}\n\n/**\n * Seeded stochastic stages (the sensor stage). Random states are integer arithmetic and bit-identical to\n * the reference. A site is flagged when any float32 decision (sampling test, saturation limit, rounding)\n * fell inside its a-priori bound. Every unflagged site has exactly the reference code and flags; only\n * flagged sites may differ, and the statistical-equivalence tests cover them (docs/WEBGPU.md).\n */\nexport interface ImageKernelSeededRealizationBound {\n kind: \"exact-except-flagged-sites\";\n /** Number of flagged sites; equal to the execution's `diagnosticUncertaintySampleCount`. */\n flaggedSiteCount: number;\n noiseModel: { id: string; version: string };\n seedSchedule: string;\n}\n\n/**\n * #481: the WebGPU adapter a device came from, as `GPUAdapter.info` describes it (W3C WebGPU, `GPUAdapterInfo`): each field\n * is the browser's string, or empty when the browser withholds it. Diagnostic only; it never changes a result.\n */\nexport interface ImageKernelAdapterDescription {\n vendor: string;\n architecture: string;\n device: string;\n description: string;\n}\n\n/**\n * A component of the composite chart kernel's double-float32 probe (see {@link ChartCompositeProbeRecord}). The first four are the\n * outputs of the probe before 2.11.0: `two-sum` is TwoSum's low part (`s.l`), `two-product` Dekker's TwoProduct low part (`m.l`),\n * `double-word-add` the double-word sum's low part (`a.l`), `double-word-multiply` the Dekker double-word product (`q.h`, `q.l`).\n */\nexport type ChartCompositeProbeComponent = \"two-sum\" | \"two-product\" | \"double-word-add\" | \"double-word-multiply\" | \"fma-two-product\" | \"fma-double-word-multiply\";\n\n/** One probe output that differs from its expected value: the component, the probe input's index, and the float32 bits (hex). */\nexport interface ChartCompositeProbeMismatch {\n component: ChartCompositeProbeComponent;\n input: number;\n got: string;\n want: string;\n}\n\n/**\n * The composite chart kernel's device probe (docs/WEBGPU.md, \"Scene radiance on the GPU\"): how the device evaluated the kernel's\n * double-float32 building blocks, and which product path the kernel was compiled with. Diagnostic; it never changes a result.\n *\n * - `deviceClass`: `exact` (the written order, round to nearest); `contracted` (only the Dekker product paths differ, consistent\n * with a multiply and an add fused into one rounding); `reassociated` (a sum path differs and every differing sum low part is\n * zero, the value an algebraic simplification of (a + b) − a to b gives); `other` (anything else, such as a sum path that differs\n * with non-zero low parts, as a rounding not to nearest gives, or a non-finite output).\n * - `productPath`: `dekker` when the Dekker path passes, else `fma` when the fma path passes (which needs a fused `fma`), else null\n * (the device is refused for composite charts, the 2.3 elements and material-layers scenes).\n * - `fmaFused`: whether every fma TwoProduct low part was exact (a fused `fma`; WGSL also allows an unfused one).\n */\nexport interface ChartCompositeProbeRecord {\n deviceClass: \"exact\" | \"contracted\" | \"reassociated\" | \"other\";\n productPath: \"dekker\" | \"fma\" | null;\n fmaFused: boolean;\n /** Probe inputs, each checked on every component. */\n inputs: number;\n /** Differing outputs per component. */\n mismatchCounts: Readonly<Record<ChartCompositeProbeComponent, number>>;\n /** The indices of the probe inputs (`PROBE_INPUTS`) whose output differs, per component. */\n mismatchedInputs: Readonly<Record<ChartCompositeProbeComponent, readonly number[]>>;\n /** The first differing outputs (at most eight), in component order. */\n mismatches: readonly ChartCompositeProbeMismatch[];\n}\n\n/** Label attached to every accelerated result. */\nexport interface ImageKernelExecution {\n backend: ImageKernelBackend;\n requestedBackend: ImageKernelBackend;\n fallbackReason: ImageKernelFallbackReason | null;\n arithmetic: \"float64\" | \"float32\";\n assurance: \"engine-reference\" | \"approximation-with-a-priori-bound\";\n /**\n * The exact-or-fast flag in the facade's words (#395): false for `cpu-reference` (the engine reference), true for\n * `webgpu-f32` (a bounded approximation). `backend` still names where the work ran.\n */\n fast: boolean;\n /**\n * True only for `cpu-reference`. Bit-exact identities (SHA-256 artifact bindings, byte-parity fixtures,\n * cross-engine determinism hashes) are CPU-only and must never be computed from a `webgpu-f32` result.\n */\n bitIdenticalToReference: boolean;\n errorBound: ImageKernelCodeErrorBound | ImageKernelRelativeErrorBound | ImageKernelSeededRealizationBound | null;\n /**\n * Diagnostic counts equal the reference when no sample fell inside a float32 classification band\n * (`diagnosticUncertaintySampleCount === 0`). Otherwise each count differs by at most that many\n * samples.\n */\n diagnosticsExact: boolean;\n diagnosticUncertaintySampleCount: number;\n limitations: readonly string[];\n}\n\n/** IEEE 754 binary32 unit roundoff. */\nexport const WEBGPU_F32_UNIT_ROUNDOFF = 2 ** -24;\n/**\n * Declared absolute error bound for the WGSL sRGB encode on [0, 1]: `1.055·pow(x, 1/2.4) − 0.055`. pow\n * takes its accuracy from exp2(y·log2 x) (log2: 3 ULP, or 2^-21 absolute on [0.5, 2]; exp2: 3 + 2|x|\n * ULP). The worst case over [0.0031308, 1] is about 2.5e-6. The bound 2^-17 ≈ 7.6e-6 keeps a 3× margin,\n * and also covers the small jump where the sRGB segments join (< 1e-7).\n */\nexport const WEBGPU_F32_TRANSFER_ABSOLUTE_BOUND = 2 ** -17;\n/** Largest slope of the sRGB encode on [0, 1] (the linear segment, 12.92). */\nexport const SRGB_ENCODE_LIPSCHITZ = 12.92;\n\n/** Higham's γ_k for binary32. */\nexport function float32Gamma(k: number): number {\n const ku = k * WEBGPU_F32_UNIT_ROUNDOFF;\n return ku < 1 ? ku / (1 - ku) : Number.POSITIVE_INFINITY;\n}\n\n/** Integer-code bound from a bound on the linear value: |Δcode| ≤ ⌊maximum·(12.92·δ_L + δ_E)⌋ + 1, capped at maximum. */\nexport function integerCodeBound(maximum: number, linearAbsoluteBound: number): ImageKernelCodeErrorBound {\n const linear = Math.min(1, linearAbsoluteBound);\n const real = maximum * (SRGB_ENCODE_LIPSCHITZ * linear + WEBGPU_F32_TRANSFER_ABSOLUTE_BOUND);\n return { kind: \"integer-code-difference\", maximumAbsoluteCodeDifference: Math.min(maximum, Math.floor(real) + 1),\n linearAbsoluteBound: linear, transferAbsoluteBound: WEBGPU_F32_TRANSFER_ABSOLUTE_BOUND };\n}\n\n/**\n * Composes two `relative-to-reference` bounds through a pipeline `second ∘ first`, where the second\n * stage is linear with non-negative weights summing to at most `secondWeightSum` per output (convolution,\n * temporal sums). With |ã − a| ≤ r₁a + a₁ elementwise and |B̃x − Bx| ≤ r₂Bx + a₂:\n * |B̃ã − Ba| ≤ |B̃ã − Bã| + |B(ã − a)| ≤ r₂(1 + r₁)Ba + r₂W·a₁ + a₂ + r₁Ba + W·a₁,\n * so r = r₁ + r₂ + r₁r₂ and a = a₂ + W·a₁·(1 + r₂). See docs/WEBGPU.md, \"Accuracy contract\".\n */\nexport function composeRelativeErrorBounds(first: ImageKernelRelativeErrorBound, second: ImageKernelRelativeErrorBound,\n secondWeightSum: number): ImageKernelRelativeErrorBound {\n requireInputObject(first, \"composeRelativeErrorBounds first bound\");\n requireInputObject(second, \"composeRelativeErrorBounds second bound\");\n for (const v of [first.relative, first.absolute, second.relative, second.absolute, secondWeightSum]) {\n if (!(typeof v === \"number\" && v >= 0 && v <= Number.MAX_VALUE)) {\n throw new InvalidScientificInputError(\"Error bounds and weight sums must be finite and non-negative.\");\n }\n }\n return { kind: \"relative-to-reference\", relative: first.relative + second.relative + first.relative * second.relative,\n absolute: second.absolute + secondWeightSum * first.absolute * (1 + second.relative) };\n}\n\nexport const CPU_REFERENCE_LIMITATIONS = Object.freeze([\"Float64 engine reference execution; results are the reference by definition\"]);\nexport const WEBGPU_F32_LIMITATIONS = Object.freeze([\n \"Float32 WebGPU execution is an approximation of the float64 reference within the reported a-priori bound\",\n \"Not bit-identical to the reference: never use for SHA-256 artifact identities, byte-parity evidence or determinism hashes\",\n \"Bound assumes a conforming WebGPU implementation (correctly rounded f32 add/multiply/divide, WGSL accuracy table)\",\n \"Execution speed depends on the adapter; software adapters do not represent GPU performance\"\n]);\n\nexport function cpuExecution(requestedBackend: ImageKernelBackend, fallbackReason: ImageKernelFallbackReason | null): ImageKernelExecution {\n return { backend: \"cpu-reference\", requestedBackend, fallbackReason, arithmetic: \"float64\", assurance: \"engine-reference\", fast: false,\n bitIdenticalToReference: true, errorBound: null, diagnosticsExact: true, diagnosticUncertaintySampleCount: 0, limitations: CPU_REFERENCE_LIMITATIONS };\n}\n\nexport function webGpuExecution(errorBound: ImageKernelExecution[\"errorBound\"], uncertainty: number): ImageKernelExecution {\n return { 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 };\n}\n"]}
|
|
@@ -23,6 +23,17 @@ export declare function twelveBitPieces(value: number): {
|
|
|
23
23
|
pieces: number[];
|
|
24
24
|
residual: number;
|
|
25
25
|
};
|
|
26
|
+
/**
|
|
27
|
+
* A 12-bit piece as the kernel reads it: an integer mantissa m < 2^12, the exponent s and the exact scale 2^s,
|
|
28
|
+
* with piece = m·2^s exactly. A zero piece is (0, 0, 1).
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
31
|
+
export declare function pieceWords(piece: number): [mantissa: number, exponent: number, scale: number];
|
|
32
|
+
/**
|
|
33
|
+
* Writes the four pieces of a positive gain-like value into the auxiliary table.
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
export declare function writePieces(aux: Float32Array, at: number, pieces: readonly number[]): void;
|
|
26
37
|
/**
|
|
27
38
|
* `L(k) − S(k)` for k < 256, where L is the reference's log k! (the summed logarithms of
|
|
28
39
|
* `samplePoisson`'s logFactorial) and S(k) = (k + ½) ln k − k + ½ ln 2π.
|
|
@@ -9,7 +9,7 @@ import { calculatePackedSensorRawPlan, createPackedFixedPattern, packedSensorDia
|
|
|
9
9
|
import { adcTransfer } from "../sensor/raw-readout.js";
|
|
10
10
|
import { ImageKernelExecutionError, webGpuExecution } from "./image-kernel-execution.js";
|
|
11
11
|
import { BUFFER_USAGE, GpuResourceScope, abortedError, linearDispatch, runComputePass } from "./webgpu-runtime.js";
|
|
12
|
-
import { SENSOR_AUX, SENSOR_EXTRAS, SENSOR_MEAN_CATEGORY, SENSOR_OUTPUT, SENSOR_RAW_WGSL, SENSOR_SITE_WORDS, SENSOR_WORKGROUP_SIZE } from "./wgsl-sensor-kernel.js";
|
|
12
|
+
import { SENSOR_AUX, SENSOR_EXTRAS, SENSOR_MEAN_CATEGORY, SENSOR_OUTPUT, SENSOR_PIECE_WORDS, SENSOR_RAW_WGSL, SENSOR_ROUNDING, SENSOR_SITE_WORDS, SENSOR_WORKGROUP_SIZE } from "./wgsl-sensor-kernel.js";
|
|
13
13
|
/** Largest physical capacity on the GPU: every realized count up to it is exact in float32. */
|
|
14
14
|
export const SENSOR_GPU_MAXIMUM_CAPACITY = 2 ** 24;
|
|
15
15
|
/** Poisson means must stay below this on the GPU (30-bit integer part of a mean word). */
|
|
@@ -18,7 +18,8 @@ export const SENSOR_GPU_MAXIMUM_MEAN = 2 ** 30;
|
|
|
18
18
|
export const SENSOR_GPU_MAXIMUM_OFFSET_ELECTRONS = 2 ** 28;
|
|
19
19
|
export const SENSOR_GPU_MAXIMUM_OFFSET_CODES = 2 ** 20;
|
|
20
20
|
const CPU_RELATIVE = 2 ** -47;
|
|
21
|
-
|
|
21
|
+
/** One WGSL rounding, either direction (2^-23). */
|
|
22
|
+
const E = SENSOR_ROUNDING;
|
|
22
23
|
const POISSON_NORMAL_MINIMUM_MEAN = 1e9;
|
|
23
24
|
function checkAbort(signal) {
|
|
24
25
|
if (signal.aborted)
|
|
@@ -67,6 +68,31 @@ export function twelveBitPieces(value) {
|
|
|
67
68
|
}
|
|
68
69
|
return { pieces, residual: rest };
|
|
69
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* A 12-bit piece as the kernel reads it: an integer mantissa m < 2^12, the exponent s and the exact scale 2^s,
|
|
73
|
+
* with piece = m·2^s exactly. A zero piece is (0, 0, 1).
|
|
74
|
+
* @internal
|
|
75
|
+
*/
|
|
76
|
+
export function pieceWords(piece) {
|
|
77
|
+
if (piece === 0)
|
|
78
|
+
return [0, 0, 1];
|
|
79
|
+
let e = Math.floor(Math.log2(piece));
|
|
80
|
+
if (piece / 2 ** e >= 2)
|
|
81
|
+
e++;
|
|
82
|
+
if (piece / 2 ** e < 1)
|
|
83
|
+
e--;
|
|
84
|
+
const s = e - 11, m = piece / 2 ** s;
|
|
85
|
+
if (!Number.isInteger(m) || m >= 4096 || s < -126 || s > 60)
|
|
86
|
+
throw new ImageKernelExecutionError("unsupported-float32-domain", "A gain piece is outside the float32 sensor domain.");
|
|
87
|
+
return [m, s, 2 ** s];
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Writes the four pieces of a positive gain-like value into the auxiliary table.
|
|
91
|
+
* @internal
|
|
92
|
+
*/
|
|
93
|
+
export function writePieces(aux, at, pieces) {
|
|
94
|
+
pieces.forEach((piece, j) => aux.set(pieceWords(piece), at + SENSOR_PIECE_WORDS * j));
|
|
95
|
+
}
|
|
70
96
|
/**
|
|
71
97
|
* `L(k) − S(k)` for k < 256, where L is the reference's log k! (the summed logarithms of
|
|
72
98
|
* `samplePoisson`'s logFactorial) and S(k) = (k + ½) ln k − k + ½ ln 2π.
|
|
@@ -99,25 +125,27 @@ export function sensorGpuConstants(plan) {
|
|
|
99
125
|
plan.additionalChargeComponents.some(c => !(c.maximumExpectedElectrons < SENSOR_GPU_MAXIMUM_MEAN))) {
|
|
100
126
|
throw unsupported("Expected electrons of 2^30 and above are outside the float32 sensor domain.");
|
|
101
127
|
}
|
|
128
|
+
if (adc.digitalGain !== undefined && !(adc.digitalGain >= 2 ** -60 && adc.digitalGain <= 2 ** 60)) {
|
|
129
|
+
throw unsupported("Digital gain is outside the float32 sensor domain.");
|
|
130
|
+
}
|
|
102
131
|
if (!(inverse >= 2 ** -60 && inverse <= 2 ** 60) || capacity * inverse > 2 ** 30 ||
|
|
103
132
|
sigmas.some(s => s !== 0 && !(s >= 2 ** -100 && s <= 2 ** 100)) || 7 * sigmaSum > 2 ** 28 || 7 * sigmaSum * inverse > 2 ** 20) {
|
|
104
133
|
throw unsupported("Conversion gain or read noise is outside the float32 sensor domain.");
|
|
105
134
|
}
|
|
106
135
|
const knots = adc.integralNonLinearity?.knots ?? [];
|
|
107
|
-
|
|
108
|
-
knots.
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
});
|
|
113
|
-
const aux = new Float32Array(SENSOR_AUX.knots + 2 * knots.length);
|
|
136
|
+
// Segment slopes in float64 on the host, so the kernel's INL offset needs no division. Codes, offsets, slopes.
|
|
137
|
+
const slopes = knots.slice(1).map((k, i) => (k.offsetCodes - knots[i].offsetCodes) / (k.code - knots[i].code));
|
|
138
|
+
const slope = slopes.reduce((m, v) => Math.max(m, Math.abs(v)), 0), offset = knots.reduce((m, k) => Math.max(m, Math.abs(k.offsetCodes)), 0);
|
|
139
|
+
const knotMagnitude = knots.reduce((m, k) => Math.max(m, Math.abs(k.code)), 0);
|
|
140
|
+
const aux = new Float32Array(SENSOR_AUX.knots + 3 * knots.length);
|
|
114
141
|
aux.set(stirlingRemainderTable(), SENSOR_AUX.stirlingRemainder);
|
|
115
142
|
aux.set(sigmas, SENSOR_AUX.sigma);
|
|
116
143
|
const inversePieces = twelveBitPieces(inverse), digital = adc.digitalGain === undefined ? null : twelveBitPieces(adc.digitalGain);
|
|
117
|
-
aux.
|
|
144
|
+
writePieces(aux, SENSOR_AUX.inversePieces, inversePieces.pieces);
|
|
118
145
|
if (digital)
|
|
119
|
-
aux
|
|
146
|
+
writePieces(aux, SENSOR_AUX.digitalPieces, digital.pieces);
|
|
120
147
|
knots.forEach((k, i) => { aux[SENSOR_AUX.knots + i] = k.code; aux[SENSOR_AUX.knots + knots.length + i] = k.offsetCodes; });
|
|
148
|
+
slopes.forEach((v, i) => { aux[SENSOR_AUX.knots + 2 * knots.length + i] = v; });
|
|
121
149
|
// Pre-ADC-saturated sites all have the same rounded ADC input; computed once with the reference, before digital gain.
|
|
122
150
|
const { digitalGain: _omitted, ...withoutDigital } = adc;
|
|
123
151
|
void _omitted;
|
|
@@ -155,6 +183,7 @@ export function sensorGpuConstants(plan) {
|
|
|
155
183
|
floats[21] = digital ? digital.residual * (1 + 2 ** -20) : 0;
|
|
156
184
|
floats[22] = slope * (1 + 2 ** -20);
|
|
157
185
|
floats[23] = offset;
|
|
186
|
+
floats[30] = knotMagnitude;
|
|
158
187
|
const siteWords = SENSOR_SITE_WORDS + 2 * poissonComponents.length + (deterministic ? 2 : 0) + (pattern ? 4 : 0);
|
|
159
188
|
words[24] = siteWords;
|
|
160
189
|
words[25] = poissonComponents.length;
|
|
@@ -166,8 +195,8 @@ function setFixedPatternSlack(params, threshold, maximumOffset, maximumOffsetCod
|
|
|
166
195
|
const floats = new Float32Array(params);
|
|
167
196
|
// The reference adds the offset in float64 and the host forms threshold − offset and offset/gain in float64.
|
|
168
197
|
floats[28] = CPU_RELATIVE * (maximumOffset + Math.min(threshold, 2 ** 30)) * (1 + 2 ** -20);
|
|
169
|
-
// The offset fraction's float32 rounding
|
|
170
|
-
floats[29] = (
|
|
198
|
+
// The offset fraction's float32 rounding (its place in the fraction sum is counted by the kernel) and offset/gain's float64 rounding.
|
|
199
|
+
floats[29] = (E + CPU_RELATIVE * maximumOffsetCodes) * (1 + 2 ** -20);
|
|
171
200
|
}
|
|
172
201
|
/** Splits a value into a floor and its float32 fraction. */
|
|
173
202
|
function packSplit(value, words, floats, at) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sensor-stage-gpu.js","sourceRoot":"","sources":["../../src/gpu/sensor-stage-gpu.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Host side of the `webgpu-f32` sensor stage (#277): domain checks, frame constants, per-site mean\n * packing, banded dispatch and readback. The float64 reference is `simulatePackedSensorRaw`\n * (capture/packed-sensor-raw.ts). Internal; the public entry point is the image-kernel accelerator.\n */\nimport { createHostYieldGate } from \"../capture/host-yield-cadence.js\";\nimport { calculatePackedSensorRawPlan, createPackedFixedPattern, packedSensorDiagnostics, packedSensorExtras, simulatePackedSensorRows,\n type PackedSensorRawInput, type PackedSensorRawPlan } from \"../capture/packed-sensor-raw.js\";\nimport { adcTransfer, type SensorReadoutConversionRegime } from \"../sensor/raw-readout.js\";\nimport { ImageKernelExecutionError, webGpuExecution, type ImageKernelExecution } from \"./image-kernel-execution.js\";\nimport type { AcceleratedPackedSensorRawResult } from \"./image-kernel-accelerator.js\";\nimport { BUFFER_USAGE, GpuResourceScope, abortedError, linearDispatch, runComputePass, type WebGpuRuntime } from \"./webgpu-runtime.js\";\nimport { SENSOR_AUX, SENSOR_EXTRAS, SENSOR_MEAN_CATEGORY, SENSOR_OUTPUT, SENSOR_RAW_WGSL, SENSOR_SITE_WORDS, SENSOR_WORKGROUP_SIZE } from \"./wgsl-sensor-kernel.js\";\n\ntype PipelineSource = (label: string, code: string) => Promise<GPUComputePipeline>;\ntype YieldControl = ((signal: AbortSignal) => Promise<void>) | undefined;\n\n/** Largest physical capacity on the GPU: every realized count up to it is exact in float32. */\nexport const SENSOR_GPU_MAXIMUM_CAPACITY = 2 ** 24;\n/** Poisson means must stay below this on the GPU (30-bit integer part of a mean word). */\nexport const SENSOR_GPU_MAXIMUM_MEAN = 2 ** 30;\n/** Largest |fixed-pattern readout offset| on the GPU, in electrons and in codes. */\nexport const SENSOR_GPU_MAXIMUM_OFFSET_ELECTRONS = 2 ** 28;\nexport const SENSOR_GPU_MAXIMUM_OFFSET_CODES = 2 ** 20;\nconst CPU_RELATIVE = 2 ** -47;\nconst U = 2 ** -24;\nconst POISSON_NORMAL_MINIMUM_MEAN = 1e9;\n\nfunction checkAbort(signal: AbortSignal): void {\n if (signal.aborted) throw abortedError();\n}\n\n/** CPU reference with host yields and abort, row-chunked; codes equal `simulatePackedSensorRaw`. */\nexport async function simulateSensorRawOnCpu(input: PackedSensorRawInput, abort: AbortController, yieldControl: YieldControl,\n execution: ImageKernelExecution): Promise<AcceleratedPackedSensorRawResult> {\n const plan = calculatePackedSensorRawPlan(input);\n // Snapshot so a caller mutation during host yields cannot change the reference.\n const photo = input.photoElectrons.slice(), dark = input.darkElectrons.slice(), extras = packedSensorExtras(plan, input, true);\n const codes = new Uint16Array(plan.siteCount), counts = [0, 0, 0, 0];\n const rowsPerChunk = Math.max(1, Math.floor(65_536 / plan.region.width)), gate = createHostYieldGate();\n for (let row = 0; row < plan.region.height; row += rowsPerChunk) {\n checkAbort(abort.signal);\n simulatePackedSensorRows(plan, photo, dark, row, Math.min(plan.region.height, row + rowsPerChunk), codes, counts, extras);\n if (yieldControl && gate.due()) { await yieldControl(abort.signal); gate.restart(); }\n }\n checkAbort(abort.signal);\n return { plan, codes, diagnostics: packedSensorDiagnostics(counts), execution, flaggedSiteIndices: new Uint32Array(0) };\n}\n\n/**\n * Splits a positive value into four non-negative pieces with at most 12 significant bits each (by\n * truncation), so that the product of any integer below 2^12 and a piece is exact in float32. Returns\n * the pieces and the non-negative remainder (below 2^-44 of the value).\n * @internal\n */\nexport function twelveBitPieces(value: number): { pieces: number[]; residual: number } {\n const pieces: number[] = [];\n let rest = value;\n for (let j = 0; j < 4; j++) {\n if (!(rest > 0)) { pieces.push(0); continue; }\n let e = Math.floor(Math.log2(rest));\n if (rest / 2 ** e >= 2) e++;\n if (rest / 2 ** e < 1) e--;\n const scale = 2 ** (e - 11), piece = Math.floor(rest / scale) * scale;\n pieces.push(piece);\n rest -= piece;\n }\n return { pieces, residual: rest };\n}\n\n/**\n * `L(k) − S(k)` for k < 256, where L is the reference's log k! (the summed logarithms of\n * `samplePoisson`'s logFactorial) and S(k) = (k + ½) ln k − k + ½ ln 2π.\n * @internal\n */\nexport function stirlingRemainderTable(): Float64Array {\n const table = new Float64Array(256);\n let sum = 0;\n for (let k = 1; k < 256; k++) {\n if (k >= 2) sum += Math.log(k);\n table[k] = sum - ((k + 0.5) * Math.log(k) - k + 0.5 * Math.log(2 * Math.PI));\n }\n return table;\n}\n\nfunction unsupported(message: string): ImageKernelExecutionError {\n return new ImageKernelExecutionError(\"unsupported-float32-domain\", message);\n}\n\ninterface SensorConstants { aux: Float32Array<ArrayBuffer>; params: ArrayBuffer; siteWords: number; poissonComponents: number[];\n deterministicComponents: number[]; threshold: number; gain: number }\n\n/** Checks the float32 execution domain and builds the frame constants (see docs/WEBGPU.md). @internal */\nexport function sensorGpuConstants(plan: PackedSensorRawPlan): SensorConstants {\n const regime = plan.readout.regime, adc = regime.adc, capacity = plan.physicalChargeCapacityElectrons;\n const gain = regime.systemConversionGainElectronsPerCode.value, inverse = 1 / gain;\n const threshold = regime.preAdcSaturationElectronEquivalent.value;\n const sigmas = regime.readNoiseComponents.map(c => c.rmsElectrons.value);\n const sigmaSum = sigmas.reduce((s, v) => s + v, 0);\n if (capacity > SENSOR_GPU_MAXIMUM_CAPACITY) throw unsupported(\"Physical capacity above 2^24 electrons is outside the float32 sensor domain.\");\n // Fixed-pattern factors scale the means; those are checked per site while packing.\n if (!(plan.maximumPhotoElectrons < SENSOR_GPU_MAXIMUM_MEAN && plan.maximumDarkElectrons < SENSOR_GPU_MAXIMUM_MEAN) ||\n plan.additionalChargeComponents.some(c => !(c.maximumExpectedElectrons < SENSOR_GPU_MAXIMUM_MEAN))) {\n throw unsupported(\"Expected electrons of 2^30 and above are outside the float32 sensor domain.\");\n }\n if (!(inverse >= 2 ** -60 && inverse <= 2 ** 60) || capacity * inverse > 2 ** 30 ||\n sigmas.some(s => s !== 0 && !(s >= 2 ** -100 && s <= 2 ** 100)) || 7 * sigmaSum > 2 ** 28 || 7 * sigmaSum * inverse > 2 ** 20) {\n throw unsupported(\"Conversion gain or read noise is outside the float32 sensor domain.\");\n }\n const knots = adc.integralNonLinearity?.knots ?? [];\n let slope = 0, offset = 0;\n knots.forEach((k, i) => {\n offset = Math.max(offset, Math.abs(k.offsetCodes));\n if (i > 0) slope = Math.max(slope, Math.abs((k.offsetCodes - knots[i - 1]!.offsetCodes) / (k.code - knots[i - 1]!.code)));\n });\n const aux = new Float32Array(SENSOR_AUX.knots + 2 * knots.length);\n aux.set(stirlingRemainderTable(), SENSOR_AUX.stirlingRemainder);\n aux.set(sigmas, SENSOR_AUX.sigma);\n const inversePieces = twelveBitPieces(inverse), digital = adc.digitalGain === undefined ? null : twelveBitPieces(adc.digitalGain);\n aux.set(inversePieces.pieces, SENSOR_AUX.inversePieces);\n if (digital) aux.set(digital.pieces, SENSOR_AUX.digitalPieces);\n knots.forEach((k, i) => { aux[SENSOR_AUX.knots + i] = k.code; aux[SENSOR_AUX.knots + knots.length + i] = k.offsetCodes; });\n // Pre-ADC-saturated sites all have the same rounded ADC input; computed once with the reference, before digital gain.\n const { digitalGain: _omitted, ...withoutDigital } = adc;\n void _omitted;\n const saturated = adcTransfer({ ...regime, adc: withoutDigital } as SensorReadoutConversionRegime, plan.readout.adcMaximumCode, threshold).quantized;\n const params = new ArrayBuffer(128), words = new Uint32Array(params), ints = new Int32Array(params), floats = new Float32Array(params);\n const capacityFloor = Math.floor(capacity), thresholdFloor = Math.min(Math.floor(threshold), 2 ** 30);\n words[2] = plan.region.width; words[3] = plan.nativeWidth; words[4] = plan.region.x; words[5] = plan.region.y;\n // Mode bits: 1 digital gain; 2 the digital-gain product is exact on both sides (gain has ≤ 12 significant\n // bits); 4 the ADC input is exact on both sides (no read noise, power-of-two gain, integer capacity, no INL).\n // In an exact mode both evaluations give the same dyadic value, so a tie is decided identically and needs no flag.\n const digitalExact = digital !== null && digital.residual === 0 && digital.pieces.slice(1).every(p => p === 0);\n const poissonComponents: number[] = [], deterministicComponents: number[] = [];\n plan.additionalChargeComponents.forEach((c, k) => (c.model === \"poisson\" ? poissonComponents : deterministicComponents).push(k));\n const deterministic = deterministicComponents.length > 0, pattern = plan.fixedPatternNoise !== null;\n const idealExact = sigmas.every(s => s === 0) && Number.isInteger(Math.log2(gain)) && Number.isInteger(capacity) && knots.length === 0 &&\n !deterministic && !pattern;\n words[6] = plan.captureSeedUint32; words[7] = sigmas.length; words[8] = knots.length;\n words[9] = (digital ? 1 : 0) | (digitalExact ? 2 : 0) | (idealExact ? 4 : 0);\n words[10] = adc.digitalSaturationCode; words[11] = plan.readout.adcMaximumCode; words[12] = capacityFloor; words[13] = thresholdFloor;\n words[14] = adc.blackLevelCode; ints[15] = Math.max(-(2 ** 30), Math.min(2 ** 30, saturated));\n floats[16] = capacity - capacityFloor; floats[17] = threshold < 2 ** 30 ? threshold - thresholdFloor : 0;\n floats[18] = inverse; floats[19] = inversePieces.residual * (1 + 2 ** -20);\n floats[20] = adc.digitalGain ?? 1; floats[21] = digital ? digital.residual * (1 + 2 ** -20) : 0;\n floats[22] = slope * (1 + 2 ** -20); floats[23] = offset;\n const siteWords = SENSOR_SITE_WORDS + 2 * poissonComponents.length + (deterministic ? 2 : 0) + (pattern ? 4 : 0);\n words[24] = siteWords; words[25] = poissonComponents.length;\n words[26] = (deterministic ? SENSOR_EXTRAS.deterministic : 0) | (pattern ? SENSOR_EXTRAS.fixedPattern : 0);\n return { aux, params, siteWords, poissonComponents, deterministicComponents, threshold, gain };\n}\n\n/** Writes the float64 slack terms of the fixed-pattern bounds, from the region's largest offsets. */\nfunction setFixedPatternSlack(params: ArrayBuffer, threshold: number, maximumOffset: number, maximumOffsetCodes: number): void {\n const floats = new Float32Array(params);\n // The reference adds the offset in float64 and the host forms threshold − offset and offset/gain in float64.\n floats[28] = CPU_RELATIVE * (maximumOffset + Math.min(threshold, 2 ** 30)) * (1 + 2 ** -20);\n // The offset fraction's float32 rounding, one more unit of |fp| across the ten fraction additions, and offset/gain's float64 rounding.\n floats[29] = (12 * U + CPU_RELATIVE * maximumOffsetCodes) * (1 + 2 ** -20);\n}\n\n/** Splits a value into a floor and its float32 fraction. */\nfunction packSplit(value: number, words: Int32Array, floats: Float32Array, at: number): void {\n const whole = Math.floor(value);\n words[at] = whole; floats[at + 1] = value - whole;\n}\n\n/** Packs one mean: category in bits 30–31 with the integer part, and the float32 fraction. */\nfunction packMean(mean: number, words: Uint32Array, floats: Float32Array, at: number): void {\n if (mean === 0) { words[at] = 0; floats[at + 1] = 0; return; }\n if (!(mean < SENSOR_GPU_MAXIMUM_MEAN)) throw unsupported(\"Expected electrons of 2^30 and above are outside the float32 sensor domain.\");\n const whole = Math.floor(mean);\n const category = mean < 30 ? SENSOR_MEAN_CATEGORY.multiplication : mean < POISSON_NORMAL_MINIMUM_MEAN ? SENSOR_MEAN_CATEGORY.transformedRejection\n : SENSOR_MEAN_CATEGORY.normal;\n words[at] = ((category << 30) | whole) >>> 0;\n floats[at + 1] = mean - whole;\n}\n\nexport async function simulateSensorRawOnGpu(runtime: WebGpuRuntime, bandBytes: number, input: PackedSensorRawInput, abort: AbortController,\n yieldControl: YieldControl, pipelines: PipelineSource): Promise<AcceleratedPackedSensorRawResult> {\n const plan = calculatePackedSensorRawPlan(input);\n const constants = sensorGpuConstants(plan), { aux, params, siteWords, poissonComponents, deterministicComponents, threshold, gain } = constants;\n const photo = input.photoElectrons.slice(), dark = input.darkElectrons.slice();\n const additional = (input.additionalChargeComponents ?? []).map(c => c.expectedElectrons.slice());\n const width = plan.region.width, height = plan.region.height, siteBytes = siteWords * 4;\n const pattern = createPackedFixedPattern(plan);\n // Fixed-pattern values are evaluated once, in float64 (exactly the reference's values), before any dispatch.\n const patterns = pattern === null ? null : new Float64Array(plan.siteCount * 3);\n if (patterns !== null) {\n let maximumOffset = 0, maximumOffsetCodes = 0;\n for (let row = 0, i = 0; row < height; row++) for (let column = 0; column < width; column++, i++) {\n const p = pattern!(column, row), offsetCodes = p.readoutOffsetElectrons / gain;\n patterns[i * 3] = p.photoResponseGainFactor; patterns[i * 3 + 1] = p.darkCurrentFactor; patterns[i * 3 + 2] = p.readoutOffsetElectrons;\n maximumOffset = Math.max(maximumOffset, Math.abs(p.readoutOffsetElectrons)); maximumOffsetCodes = Math.max(maximumOffsetCodes, Math.abs(offsetCodes));\n }\n if (!(maximumOffset <= SENSOR_GPU_MAXIMUM_OFFSET_ELECTRONS && maximumOffsetCodes <= SENSOR_GPU_MAXIMUM_OFFSET_CODES)) {\n throw unsupported(\"Fixed-pattern readout offsets are outside the float32 sensor domain.\");\n }\n setFixedPatternSlack(params, threshold, maximumOffset, maximumOffsetCodes);\n }\n const rows = Math.max(1, Math.min(height, Math.floor(bandBytes / (width * siteBytes))));\n if (rows * width * siteBytes > runtime.maximumStorageBindingBytes) {\n throw new ImageKernelExecutionError(\"insufficient-limits\", \"One sensor band exceeds the device's storage binding limit.\");\n }\n const pipeline = await pipelines(\"photivra-sensor-raw\", SENSOR_RAW_WGSL);\n const codes = new Uint16Array(plan.siteCount), counts = [0, 0, 0, 0];\n const packed = new ArrayBuffer(rows * width * siteBytes), packedWords = new Uint32Array(packed), packedFloats = new Float32Array(packed);\n const packedInts = new Int32Array(packed);\n const words = new Uint32Array(params);\n let flagged = 0;\n const flaggedIndices: number[] = [];\n const scope = new GpuResourceScope(runtime);\n try {\n const auxBuffer = scope.upload(\"photivra-sensor-aux\", aux, BUFFER_USAGE.STORAGE);\n const gate = createHostYieldGate();\n for (let row0 = 0; row0 < height; row0 += rows) {\n checkAbort(abort.signal);\n const row1 = Math.min(height, row0 + rows), count = (row1 - row0) * width, first = row0 * width;\n for (let i = 0; i < count; i++) {\n const site = first + i, at = i * siteWords;\n // The reference's own float64 products of the means and the fixed-pattern factors.\n packMean(patterns === null ? photo[site]! : photo[site]! * patterns[site * 3]!, packedWords, packedFloats, at);\n packMean(patterns === null ? dark[site]! : dark[site]! * patterns[site * 3 + 1]!, packedWords, packedFloats, at + 2);\n let cursor = at + 4;\n for (const k of poissonComponents) { packMean(additional[k]![site]!, packedWords, packedFloats, cursor); cursor += 2; }\n if (deterministicComponents.length > 0) {\n let sum = 0;\n for (const k of deterministicComponents) sum += additional[k]![site]!;\n if (!(sum < SENSOR_GPU_MAXIMUM_MEAN)) throw unsupported(\"Deterministic charge of 2^30 electrons and above is outside the float32 sensor domain.\");\n packSplit(sum, packedInts, packedFloats, cursor);\n cursor += 2;\n }\n if (patterns !== null) {\n const offset = patterns[site * 3 + 2]!, limit = threshold - offset;\n if (limit >= 2 ** 30) { packedInts[cursor] = 2 ** 30; packedFloats[cursor + 1] = 0; } else packSplit(limit, packedInts, packedFloats, cursor);\n packSplit(offset / gain, packedInts, packedFloats, cursor + 2);\n }\n }\n words[0] = count; words[1] = row0;\n const band = new GpuResourceScope(runtime);\n try {\n const means = band.upload(\"photivra-sensor-means\", new Uint32Array(packed, 0, count * siteWords), BUFFER_USAGE.STORAGE);\n const out = band.buffer(\"photivra-sensor-codes\", count * 4, BUFFER_USAGE.STORAGE | BUFFER_USAGE.COPY_SRC);\n const uniform = band.upload(\"photivra-sensor-params\", new Uint8Array(params), BUFFER_USAGE.UNIFORM);\n const bindGroup = runtime.device.createBindGroup({ layout: pipeline.getBindGroupLayout(0), entries: [\n { binding: 0, resource: { buffer: uniform } }, { binding: 1, resource: { buffer: means } },\n { binding: 2, resource: { buffer: auxBuffer } }, { binding: 3, resource: { buffer: out } }] });\n const [data] = await runComputePass(runtime, band, pipeline, bindGroup, linearDispatch(count, SENSOR_WORKGROUP_SIZE, runtime.maximumWorkgroupsPerDimension),\n [{ buffer: out, bytes: count * 4 }], abort.signal);\n const result = new Uint32Array(data!, 0, count);\n for (let i = 0; i < count; i++) {\n const word = result[i]!, flags = word >>> SENSOR_OUTPUT.flagShift;\n codes[first + i] = word & SENSOR_OUTPUT.codeMask;\n if (flags & 1) counts[0]!++;\n if (flags & 2) counts[1]!++;\n if (flags & 4) counts[2]!++;\n if (flags & 8) counts[3]!++;\n if (word & SENSOR_OUTPUT.uncertainBit) { flagged++; flaggedIndices.push(first + i); }\n }\n } finally {\n band.release();\n }\n if (yieldControl && gate.due()) { await yieldControl(abort.signal); gate.restart(); }\n }\n } catch (error) {\n codes.fill(0);\n throw error;\n } finally {\n scope.release();\n }\n checkAbort(abort.signal);\n const execution = webGpuExecution({ kind: \"exact-except-flagged-sites\", flaggedSiteCount: flagged, noiseModel: { ...plan.noiseModel },\n seedSchedule: plan.seedSchedule }, flagged);\n return { plan, codes, diagnostics: packedSensorDiagnostics(counts), execution, flaggedSiteIndices: Uint32Array.from(flaggedIndices) };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"sensor-stage-gpu.js","sourceRoot":"","sources":["../../src/gpu/sensor-stage-gpu.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Host side of the `webgpu-f32` sensor stage (#277): domain checks, frame constants, per-site mean\n * packing, banded dispatch and readback. The float64 reference is `simulatePackedSensorRaw`\n * (capture/packed-sensor-raw.ts). Internal; the public entry point is the image-kernel accelerator.\n */\nimport { createHostYieldGate } from \"../capture/host-yield-cadence.js\";\nimport { calculatePackedSensorRawPlan, createPackedFixedPattern, packedSensorDiagnostics, packedSensorExtras, simulatePackedSensorRows,\n type PackedSensorRawInput, type PackedSensorRawPlan } from \"../capture/packed-sensor-raw.js\";\nimport { adcTransfer, type SensorReadoutConversionRegime } from \"../sensor/raw-readout.js\";\nimport { ImageKernelExecutionError, webGpuExecution, type ImageKernelExecution } from \"./image-kernel-execution.js\";\nimport type { AcceleratedPackedSensorRawResult } from \"./image-kernel-accelerator.js\";\nimport { BUFFER_USAGE, GpuResourceScope, abortedError, linearDispatch, runComputePass, type WebGpuRuntime } from \"./webgpu-runtime.js\";\nimport { SENSOR_AUX, SENSOR_EXTRAS, SENSOR_MEAN_CATEGORY, SENSOR_OUTPUT, SENSOR_PIECE_WORDS, SENSOR_RAW_WGSL, SENSOR_ROUNDING, SENSOR_SITE_WORDS,\n SENSOR_WORKGROUP_SIZE } from \"./wgsl-sensor-kernel.js\";\n\ntype PipelineSource = (label: string, code: string) => Promise<GPUComputePipeline>;\ntype YieldControl = ((signal: AbortSignal) => Promise<void>) | undefined;\n\n/** Largest physical capacity on the GPU: every realized count up to it is exact in float32. */\nexport const SENSOR_GPU_MAXIMUM_CAPACITY = 2 ** 24;\n/** Poisson means must stay below this on the GPU (30-bit integer part of a mean word). */\nexport const SENSOR_GPU_MAXIMUM_MEAN = 2 ** 30;\n/** Largest |fixed-pattern readout offset| on the GPU, in electrons and in codes. */\nexport const SENSOR_GPU_MAXIMUM_OFFSET_ELECTRONS = 2 ** 28;\nexport const SENSOR_GPU_MAXIMUM_OFFSET_CODES = 2 ** 20;\nconst CPU_RELATIVE = 2 ** -47;\n/** One WGSL rounding, either direction (2^-23). */\nconst E = SENSOR_ROUNDING;\nconst POISSON_NORMAL_MINIMUM_MEAN = 1e9;\n\nfunction checkAbort(signal: AbortSignal): void {\n if (signal.aborted) throw abortedError();\n}\n\n/** CPU reference with host yields and abort, row-chunked; codes equal `simulatePackedSensorRaw`. */\nexport async function simulateSensorRawOnCpu(input: PackedSensorRawInput, abort: AbortController, yieldControl: YieldControl,\n execution: ImageKernelExecution): Promise<AcceleratedPackedSensorRawResult> {\n const plan = calculatePackedSensorRawPlan(input);\n // Snapshot so a caller mutation during host yields cannot change the reference.\n const photo = input.photoElectrons.slice(), dark = input.darkElectrons.slice(), extras = packedSensorExtras(plan, input, true);\n const codes = new Uint16Array(plan.siteCount), counts = [0, 0, 0, 0];\n const rowsPerChunk = Math.max(1, Math.floor(65_536 / plan.region.width)), gate = createHostYieldGate();\n for (let row = 0; row < plan.region.height; row += rowsPerChunk) {\n checkAbort(abort.signal);\n simulatePackedSensorRows(plan, photo, dark, row, Math.min(plan.region.height, row + rowsPerChunk), codes, counts, extras);\n if (yieldControl && gate.due()) { await yieldControl(abort.signal); gate.restart(); }\n }\n checkAbort(abort.signal);\n return { plan, codes, diagnostics: packedSensorDiagnostics(counts), execution, flaggedSiteIndices: new Uint32Array(0) };\n}\n\n/**\n * Splits a positive value into four non-negative pieces with at most 12 significant bits each (by\n * truncation), so that the product of any integer below 2^12 and a piece is exact in float32. Returns\n * the pieces and the non-negative remainder (below 2^-44 of the value).\n * @internal\n */\nexport function twelveBitPieces(value: number): { pieces: number[]; residual: number } {\n const pieces: number[] = [];\n let rest = value;\n for (let j = 0; j < 4; j++) {\n if (!(rest > 0)) { pieces.push(0); continue; }\n let e = Math.floor(Math.log2(rest));\n if (rest / 2 ** e >= 2) e++;\n if (rest / 2 ** e < 1) e--;\n const scale = 2 ** (e - 11), piece = Math.floor(rest / scale) * scale;\n pieces.push(piece);\n rest -= piece;\n }\n return { pieces, residual: rest };\n}\n\n/**\n * A 12-bit piece as the kernel reads it: an integer mantissa m < 2^12, the exponent s and the exact scale 2^s,\n * with piece = m·2^s exactly. A zero piece is (0, 0, 1).\n * @internal\n */\nexport function pieceWords(piece: number): [mantissa: number, exponent: number, scale: number] {\n if (piece === 0) return [0, 0, 1];\n let e = Math.floor(Math.log2(piece));\n if (piece / 2 ** e >= 2) e++;\n if (piece / 2 ** e < 1) e--;\n const s = e - 11, m = piece / 2 ** s;\n if (!Number.isInteger(m) || m >= 4096 || s < -126 || s > 60) throw new ImageKernelExecutionError(\"unsupported-float32-domain\", \"A gain piece is outside the float32 sensor domain.\");\n return [m, s, 2 ** s];\n}\n\n/**\n * Writes the four pieces of a positive gain-like value into the auxiliary table.\n * @internal\n */\nexport function writePieces(aux: Float32Array, at: number, pieces: readonly number[]): void {\n pieces.forEach((piece, j) => aux.set(pieceWords(piece), at + SENSOR_PIECE_WORDS * j));\n}\n\n/**\n * `L(k) − S(k)` for k < 256, where L is the reference's log k! (the summed logarithms of\n * `samplePoisson`'s logFactorial) and S(k) = (k + ½) ln k − k + ½ ln 2π.\n * @internal\n */\nexport function stirlingRemainderTable(): Float64Array {\n const table = new Float64Array(256);\n let sum = 0;\n for (let k = 1; k < 256; k++) {\n if (k >= 2) sum += Math.log(k);\n table[k] = sum - ((k + 0.5) * Math.log(k) - k + 0.5 * Math.log(2 * Math.PI));\n }\n return table;\n}\n\nfunction unsupported(message: string): ImageKernelExecutionError {\n return new ImageKernelExecutionError(\"unsupported-float32-domain\", message);\n}\n\ninterface SensorConstants { aux: Float32Array<ArrayBuffer>; params: ArrayBuffer; siteWords: number; poissonComponents: number[];\n deterministicComponents: number[]; threshold: number; gain: number }\n\n/** Checks the float32 execution domain and builds the frame constants (see docs/WEBGPU.md). @internal */\nexport function sensorGpuConstants(plan: PackedSensorRawPlan): SensorConstants {\n const regime = plan.readout.regime, adc = regime.adc, capacity = plan.physicalChargeCapacityElectrons;\n const gain = regime.systemConversionGainElectronsPerCode.value, inverse = 1 / gain;\n const threshold = regime.preAdcSaturationElectronEquivalent.value;\n const sigmas = regime.readNoiseComponents.map(c => c.rmsElectrons.value);\n const sigmaSum = sigmas.reduce((s, v) => s + v, 0);\n if (capacity > SENSOR_GPU_MAXIMUM_CAPACITY) throw unsupported(\"Physical capacity above 2^24 electrons is outside the float32 sensor domain.\");\n // Fixed-pattern factors scale the means; those are checked per site while packing.\n if (!(plan.maximumPhotoElectrons < SENSOR_GPU_MAXIMUM_MEAN && plan.maximumDarkElectrons < SENSOR_GPU_MAXIMUM_MEAN) ||\n plan.additionalChargeComponents.some(c => !(c.maximumExpectedElectrons < SENSOR_GPU_MAXIMUM_MEAN))) {\n throw unsupported(\"Expected electrons of 2^30 and above are outside the float32 sensor domain.\");\n }\n if (adc.digitalGain !== undefined && !(adc.digitalGain >= 2 ** -60 && adc.digitalGain <= 2 ** 60)) {\n throw unsupported(\"Digital gain is outside the float32 sensor domain.\");\n }\n if (!(inverse >= 2 ** -60 && inverse <= 2 ** 60) || capacity * inverse > 2 ** 30 ||\n sigmas.some(s => s !== 0 && !(s >= 2 ** -100 && s <= 2 ** 100)) || 7 * sigmaSum > 2 ** 28 || 7 * sigmaSum * inverse > 2 ** 20) {\n throw unsupported(\"Conversion gain or read noise is outside the float32 sensor domain.\");\n }\n const knots = adc.integralNonLinearity?.knots ?? [];\n // Segment slopes in float64 on the host, so the kernel's INL offset needs no division. Codes, offsets, slopes.\n const slopes = knots.slice(1).map((k, i) => (k.offsetCodes - knots[i]!.offsetCodes) / (k.code - knots[i]!.code));\n const slope = slopes.reduce((m, v) => Math.max(m, Math.abs(v)), 0), offset = knots.reduce((m, k) => Math.max(m, Math.abs(k.offsetCodes)), 0);\n const knotMagnitude = knots.reduce((m, k) => Math.max(m, Math.abs(k.code)), 0);\n const aux = new Float32Array(SENSOR_AUX.knots + 3 * knots.length);\n aux.set(stirlingRemainderTable(), SENSOR_AUX.stirlingRemainder);\n aux.set(sigmas, SENSOR_AUX.sigma);\n const inversePieces = twelveBitPieces(inverse), digital = adc.digitalGain === undefined ? null : twelveBitPieces(adc.digitalGain);\n writePieces(aux, SENSOR_AUX.inversePieces, inversePieces.pieces);\n if (digital) writePieces(aux, SENSOR_AUX.digitalPieces, digital.pieces);\n knots.forEach((k, i) => { aux[SENSOR_AUX.knots + i] = k.code; aux[SENSOR_AUX.knots + knots.length + i] = k.offsetCodes; });\n slopes.forEach((v, i) => { aux[SENSOR_AUX.knots + 2 * knots.length + i] = v; });\n // Pre-ADC-saturated sites all have the same rounded ADC input; computed once with the reference, before digital gain.\n const { digitalGain: _omitted, ...withoutDigital } = adc;\n void _omitted;\n const saturated = adcTransfer({ ...regime, adc: withoutDigital } as SensorReadoutConversionRegime, plan.readout.adcMaximumCode, threshold).quantized;\n const params = new ArrayBuffer(128), words = new Uint32Array(params), ints = new Int32Array(params), floats = new Float32Array(params);\n const capacityFloor = Math.floor(capacity), thresholdFloor = Math.min(Math.floor(threshold), 2 ** 30);\n words[2] = plan.region.width; words[3] = plan.nativeWidth; words[4] = plan.region.x; words[5] = plan.region.y;\n // Mode bits: 1 digital gain; 2 the digital-gain product is exact on both sides (gain has ≤ 12 significant\n // bits); 4 the ADC input is exact on both sides (no read noise, power-of-two gain, integer capacity, no INL).\n // In an exact mode both evaluations give the same dyadic value, so a tie is decided identically and needs no flag.\n const digitalExact = digital !== null && digital.residual === 0 && digital.pieces.slice(1).every(p => p === 0);\n const poissonComponents: number[] = [], deterministicComponents: number[] = [];\n plan.additionalChargeComponents.forEach((c, k) => (c.model === \"poisson\" ? poissonComponents : deterministicComponents).push(k));\n const deterministic = deterministicComponents.length > 0, pattern = plan.fixedPatternNoise !== null;\n const idealExact = sigmas.every(s => s === 0) && Number.isInteger(Math.log2(gain)) && Number.isInteger(capacity) && knots.length === 0 &&\n !deterministic && !pattern;\n words[6] = plan.captureSeedUint32; words[7] = sigmas.length; words[8] = knots.length;\n words[9] = (digital ? 1 : 0) | (digitalExact ? 2 : 0) | (idealExact ? 4 : 0);\n words[10] = adc.digitalSaturationCode; words[11] = plan.readout.adcMaximumCode; words[12] = capacityFloor; words[13] = thresholdFloor;\n words[14] = adc.blackLevelCode; ints[15] = Math.max(-(2 ** 30), Math.min(2 ** 30, saturated));\n floats[16] = capacity - capacityFloor; floats[17] = threshold < 2 ** 30 ? threshold - thresholdFloor : 0;\n floats[18] = inverse; floats[19] = inversePieces.residual * (1 + 2 ** -20);\n floats[20] = adc.digitalGain ?? 1; floats[21] = digital ? digital.residual * (1 + 2 ** -20) : 0;\n floats[22] = slope * (1 + 2 ** -20); floats[23] = offset; floats[30] = knotMagnitude;\n const siteWords = SENSOR_SITE_WORDS + 2 * poissonComponents.length + (deterministic ? 2 : 0) + (pattern ? 4 : 0);\n words[24] = siteWords; words[25] = poissonComponents.length;\n words[26] = (deterministic ? SENSOR_EXTRAS.deterministic : 0) | (pattern ? SENSOR_EXTRAS.fixedPattern : 0);\n return { aux, params, siteWords, poissonComponents, deterministicComponents, threshold, gain };\n}\n\n/** Writes the float64 slack terms of the fixed-pattern bounds, from the region's largest offsets. */\nfunction setFixedPatternSlack(params: ArrayBuffer, threshold: number, maximumOffset: number, maximumOffsetCodes: number): void {\n const floats = new Float32Array(params);\n // The reference adds the offset in float64 and the host forms threshold − offset and offset/gain in float64.\n floats[28] = CPU_RELATIVE * (maximumOffset + Math.min(threshold, 2 ** 30)) * (1 + 2 ** -20);\n // The offset fraction's float32 rounding (its place in the fraction sum is counted by the kernel) and offset/gain's float64 rounding.\n floats[29] = (E + CPU_RELATIVE * maximumOffsetCodes) * (1 + 2 ** -20);\n}\n\n/** Splits a value into a floor and its float32 fraction. */\nfunction packSplit(value: number, words: Int32Array, floats: Float32Array, at: number): void {\n const whole = Math.floor(value);\n words[at] = whole; floats[at + 1] = value - whole;\n}\n\n/** Packs one mean: category in bits 30–31 with the integer part, and the float32 fraction. */\nfunction packMean(mean: number, words: Uint32Array, floats: Float32Array, at: number): void {\n if (mean === 0) { words[at] = 0; floats[at + 1] = 0; return; }\n if (!(mean < SENSOR_GPU_MAXIMUM_MEAN)) throw unsupported(\"Expected electrons of 2^30 and above are outside the float32 sensor domain.\");\n const whole = Math.floor(mean);\n const category = mean < 30 ? SENSOR_MEAN_CATEGORY.multiplication : mean < POISSON_NORMAL_MINIMUM_MEAN ? SENSOR_MEAN_CATEGORY.transformedRejection\n : SENSOR_MEAN_CATEGORY.normal;\n words[at] = ((category << 30) | whole) >>> 0;\n floats[at + 1] = mean - whole;\n}\n\nexport async function simulateSensorRawOnGpu(runtime: WebGpuRuntime, bandBytes: number, input: PackedSensorRawInput, abort: AbortController,\n yieldControl: YieldControl, pipelines: PipelineSource): Promise<AcceleratedPackedSensorRawResult> {\n const plan = calculatePackedSensorRawPlan(input);\n const constants = sensorGpuConstants(plan), { aux, params, siteWords, poissonComponents, deterministicComponents, threshold, gain } = constants;\n const photo = input.photoElectrons.slice(), dark = input.darkElectrons.slice();\n const additional = (input.additionalChargeComponents ?? []).map(c => c.expectedElectrons.slice());\n const width = plan.region.width, height = plan.region.height, siteBytes = siteWords * 4;\n const pattern = createPackedFixedPattern(plan);\n // Fixed-pattern values are evaluated once, in float64 (exactly the reference's values), before any dispatch.\n const patterns = pattern === null ? null : new Float64Array(plan.siteCount * 3);\n if (patterns !== null) {\n let maximumOffset = 0, maximumOffsetCodes = 0;\n for (let row = 0, i = 0; row < height; row++) for (let column = 0; column < width; column++, i++) {\n const p = pattern!(column, row), offsetCodes = p.readoutOffsetElectrons / gain;\n patterns[i * 3] = p.photoResponseGainFactor; patterns[i * 3 + 1] = p.darkCurrentFactor; patterns[i * 3 + 2] = p.readoutOffsetElectrons;\n maximumOffset = Math.max(maximumOffset, Math.abs(p.readoutOffsetElectrons)); maximumOffsetCodes = Math.max(maximumOffsetCodes, Math.abs(offsetCodes));\n }\n if (!(maximumOffset <= SENSOR_GPU_MAXIMUM_OFFSET_ELECTRONS && maximumOffsetCodes <= SENSOR_GPU_MAXIMUM_OFFSET_CODES)) {\n throw unsupported(\"Fixed-pattern readout offsets are outside the float32 sensor domain.\");\n }\n setFixedPatternSlack(params, threshold, maximumOffset, maximumOffsetCodes);\n }\n const rows = Math.max(1, Math.min(height, Math.floor(bandBytes / (width * siteBytes))));\n if (rows * width * siteBytes > runtime.maximumStorageBindingBytes) {\n throw new ImageKernelExecutionError(\"insufficient-limits\", \"One sensor band exceeds the device's storage binding limit.\");\n }\n const pipeline = await pipelines(\"photivra-sensor-raw\", SENSOR_RAW_WGSL);\n const codes = new Uint16Array(plan.siteCount), counts = [0, 0, 0, 0];\n const packed = new ArrayBuffer(rows * width * siteBytes), packedWords = new Uint32Array(packed), packedFloats = new Float32Array(packed);\n const packedInts = new Int32Array(packed);\n const words = new Uint32Array(params);\n let flagged = 0;\n const flaggedIndices: number[] = [];\n const scope = new GpuResourceScope(runtime);\n try {\n const auxBuffer = scope.upload(\"photivra-sensor-aux\", aux, BUFFER_USAGE.STORAGE);\n const gate = createHostYieldGate();\n for (let row0 = 0; row0 < height; row0 += rows) {\n checkAbort(abort.signal);\n const row1 = Math.min(height, row0 + rows), count = (row1 - row0) * width, first = row0 * width;\n for (let i = 0; i < count; i++) {\n const site = first + i, at = i * siteWords;\n // The reference's own float64 products of the means and the fixed-pattern factors.\n packMean(patterns === null ? photo[site]! : photo[site]! * patterns[site * 3]!, packedWords, packedFloats, at);\n packMean(patterns === null ? dark[site]! : dark[site]! * patterns[site * 3 + 1]!, packedWords, packedFloats, at + 2);\n let cursor = at + 4;\n for (const k of poissonComponents) { packMean(additional[k]![site]!, packedWords, packedFloats, cursor); cursor += 2; }\n if (deterministicComponents.length > 0) {\n let sum = 0;\n for (const k of deterministicComponents) sum += additional[k]![site]!;\n if (!(sum < SENSOR_GPU_MAXIMUM_MEAN)) throw unsupported(\"Deterministic charge of 2^30 electrons and above is outside the float32 sensor domain.\");\n packSplit(sum, packedInts, packedFloats, cursor);\n cursor += 2;\n }\n if (patterns !== null) {\n const offset = patterns[site * 3 + 2]!, limit = threshold - offset;\n if (limit >= 2 ** 30) { packedInts[cursor] = 2 ** 30; packedFloats[cursor + 1] = 0; } else packSplit(limit, packedInts, packedFloats, cursor);\n packSplit(offset / gain, packedInts, packedFloats, cursor + 2);\n }\n }\n words[0] = count; words[1] = row0;\n const band = new GpuResourceScope(runtime);\n try {\n const means = band.upload(\"photivra-sensor-means\", new Uint32Array(packed, 0, count * siteWords), BUFFER_USAGE.STORAGE);\n const out = band.buffer(\"photivra-sensor-codes\", count * 4, BUFFER_USAGE.STORAGE | BUFFER_USAGE.COPY_SRC);\n const uniform = band.upload(\"photivra-sensor-params\", new Uint8Array(params), BUFFER_USAGE.UNIFORM);\n const bindGroup = runtime.device.createBindGroup({ layout: pipeline.getBindGroupLayout(0), entries: [\n { binding: 0, resource: { buffer: uniform } }, { binding: 1, resource: { buffer: means } },\n { binding: 2, resource: { buffer: auxBuffer } }, { binding: 3, resource: { buffer: out } }] });\n const [data] = await runComputePass(runtime, band, pipeline, bindGroup, linearDispatch(count, SENSOR_WORKGROUP_SIZE, runtime.maximumWorkgroupsPerDimension),\n [{ buffer: out, bytes: count * 4 }], abort.signal);\n const result = new Uint32Array(data!, 0, count);\n for (let i = 0; i < count; i++) {\n const word = result[i]!, flags = word >>> SENSOR_OUTPUT.flagShift;\n codes[first + i] = word & SENSOR_OUTPUT.codeMask;\n if (flags & 1) counts[0]!++;\n if (flags & 2) counts[1]!++;\n if (flags & 4) counts[2]!++;\n if (flags & 8) counts[3]!++;\n if (word & SENSOR_OUTPUT.uncertainBit) { flagged++; flaggedIndices.push(first + i); }\n }\n } finally {\n band.release();\n }\n if (yieldControl && gate.due()) { await yieldControl(abort.signal); gate.restart(); }\n }\n } catch (error) {\n codes.fill(0);\n throw error;\n } finally {\n scope.release();\n }\n checkAbort(abort.signal);\n const execution = webGpuExecution({ kind: \"exact-except-flagged-sites\", flaggedSiteCount: flagged, noiseModel: { ...plan.noiseModel },\n seedSchedule: plan.seedSchedule }, flagged);\n return { plan, codes, diagnostics: packedSensorDiagnostics(counts), execution, flaggedSiteIndices: Uint32Array.from(flaggedIndices) };\n}\n"]}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* cleanup. Not exported from the package root. WebGPU types never appear in the published type
|
|
5
5
|
* declarations, so consumers do not need WebGPU typings.
|
|
6
6
|
*/
|
|
7
|
-
import { ImageKernelExecutionError, type ImageKernelFallbackReason } from "./image-kernel-execution.js";
|
|
7
|
+
import { ImageKernelExecutionError, type ImageKernelAdapterDescription, type ImageKernelFallbackReason } from "./image-kernel-execution.js";
|
|
8
8
|
/** WebGPU spec constants (GPUBufferUsage, GPUMapMode), defined here so no global is needed at import time. */
|
|
9
9
|
export declare const BUFFER_USAGE: Readonly<{
|
|
10
10
|
MAP_READ: 1;
|
|
@@ -19,6 +19,8 @@ export declare const WEBGPU_MINIMUM_STORAGE_BINDING_BYTES: number;
|
|
|
19
19
|
export declare const WEBGPU_REQUESTED_STORAGE_BINDING_BYTES: number;
|
|
20
20
|
export interface WebGpuRuntime {
|
|
21
21
|
readonly device: GPUDevice;
|
|
22
|
+
/** #481: the adapter's `info`, or null when the implementation has none. */
|
|
23
|
+
readonly adapter: ImageKernelAdapterDescription | null;
|
|
22
24
|
readonly maximumStorageBindingBytes: number;
|
|
23
25
|
readonly maximumWorkgroupsPerDimension: number;
|
|
24
26
|
/** Set once `device.lost` settles; every later wait rejects with `device-lost`. */
|
|
@@ -55,7 +57,7 @@ export declare function linearDispatch(invocations: number, workgroupSize: numbe
|
|
|
55
57
|
* Submits one compute pass and copies `outputs` into mappable staging buffers, then maps them. Validation
|
|
56
58
|
* and out-of-memory errors are captured with error scopes and reported as domain errors.
|
|
57
59
|
*/
|
|
58
|
-
export declare function runComputePass(runtime: WebGpuRuntime, scope: GpuResourceScope, pipeline: GPUComputePipeline, bindGroup: GPUBindGroup, workgroups: readonly [number, number], outputs: readonly {
|
|
60
|
+
export declare function runComputePass(runtime: WebGpuRuntime, scope: GpuResourceScope, pipeline: GPUComputePipeline, bindGroup: GPUBindGroup | readonly GPUBindGroup[], workgroups: readonly [number, number], outputs: readonly {
|
|
59
61
|
buffer: GPUBuffer;
|
|
60
62
|
bytes: number;
|
|
61
63
|
}[], signal: AbortSignal | undefined): Promise<ArrayBuffer[]>;
|
|
@@ -85,13 +85,21 @@ export async function acquireWebGpuRuntime(gpu, powerPreference, signal) {
|
|
|
85
85
|
device.destroy();
|
|
86
86
|
throw abortedError();
|
|
87
87
|
}
|
|
88
|
-
return { runtime: createRuntime(device, storage) };
|
|
88
|
+
return { runtime: createRuntime(device, storage, describeAdapter(adapter)) };
|
|
89
89
|
}
|
|
90
90
|
finally {
|
|
91
91
|
abort.cleanup();
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
|
-
|
|
94
|
+
/** `GPUAdapter.info` as plain strings (missing or non-string fields read as empty), or null when the adapter has no `info`. */
|
|
95
|
+
function describeAdapter(adapter) {
|
|
96
|
+
const info = adapter.info;
|
|
97
|
+
if (!info || typeof info !== "object")
|
|
98
|
+
return null;
|
|
99
|
+
const text = (value) => (typeof value === "string" ? value : "");
|
|
100
|
+
return { vendor: text(info.vendor), architecture: text(info.architecture), device: text(info.device), description: text(info.description) };
|
|
101
|
+
}
|
|
102
|
+
function createRuntime(device, storage, adapter) {
|
|
95
103
|
let lost = false, destroyed = false;
|
|
96
104
|
let rejectLost = () => undefined;
|
|
97
105
|
const lostPromise = new Promise((_, reject) => { rejectLost = reject; });
|
|
@@ -104,7 +112,7 @@ function createRuntime(device, storage) {
|
|
|
104
112
|
device.onuncapturederror = (event) => { event.preventDefault(); };
|
|
105
113
|
const maximumWorkgroupsPerDimension = device.limits.maxComputeWorkgroupsPerDimension;
|
|
106
114
|
return {
|
|
107
|
-
device,
|
|
115
|
+
device, adapter,
|
|
108
116
|
maximumStorageBindingBytes: Math.min(storage, device.limits.maxStorageBufferBindingSize, device.limits.maxBufferSize),
|
|
109
117
|
maximumWorkgroupsPerDimension,
|
|
110
118
|
isLost: () => lost,
|
|
@@ -169,7 +177,8 @@ export async function runComputePass(runtime, scope, pipeline, bindGroup, workgr
|
|
|
169
177
|
const encoder = device.createCommandEncoder({ label: "photivra-image-kernel" });
|
|
170
178
|
const pass = encoder.beginComputePass();
|
|
171
179
|
pass.setPipeline(pipeline);
|
|
172
|
-
|
|
180
|
+
// One bind group at index 0, or several at indices 0, 1, … (the display-view kernel binds its material module at 1).
|
|
181
|
+
(Array.isArray(bindGroup) ? bindGroup : [bindGroup]).forEach((group, index) => pass.setBindGroup(index, group));
|
|
173
182
|
pass.dispatchWorkgroups(workgroups[0], workgroups[1]);
|
|
174
183
|
pass.end();
|
|
175
184
|
outputs.forEach(({ buffer }, i) => encoder.copyBufferToBuffer(buffer, 0, staging[i], 0, staging[i].size));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webgpu-runtime.js","sourceRoot":"","sources":["../../src/gpu/webgpu-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Internal WebGPU device handling for the image-kernel accelerator: getting the adapter and device,\n * limits, tracking device loss, racing work against abort and loss, error scopes, banded buffers and\n * cleanup. Not exported from the package root. WebGPU types never appear in the published type\n * declarations, so consumers do not need WebGPU typings.\n */\nimport { ImageKernelExecutionError, type ImageKernelFallbackReason } from \"./image-kernel-execution.js\";\n\n/** WebGPU spec constants (GPUBufferUsage, GPUMapMode), defined here so no global is needed at import time. */\nexport const BUFFER_USAGE = Object.freeze({ MAP_READ: 0x0001, COPY_SRC: 0x0004, COPY_DST: 0x0008, UNIFORM: 0x0040, STORAGE: 0x0080 });\nconst MAP_MODE_READ = 0x0001;\n\n/** Minimum per-binding storage this backend requires (the WebGPU default is 128 MiB). */\nexport const WEBGPU_MINIMUM_STORAGE_BINDING_BYTES = 16 * 1024 * 1024;\n/** Upper limit requested from the adapter, so one band never asks for more than this per binding. */\nexport const WEBGPU_REQUESTED_STORAGE_BINDING_BYTES = 1024 * 1024 * 1024;\n\nexport interface WebGpuRuntime {\n readonly device: GPUDevice;\n readonly maximumStorageBindingBytes: number;\n readonly maximumWorkgroupsPerDimension: number;\n /** Set once `device.lost` settles; every later wait rejects with `device-lost`. */\n isLost(): boolean;\n /** Races a GPU promise with device loss and the operation's abort signal. */\n guard<T>(promise: Promise<T>, signal: AbortSignal | undefined): Promise<T>;\n destroy(): void;\n}\n\nexport type WebGpuAcquisition = { runtime: WebGpuRuntime } | { failure: ImageKernelFallbackReason; message: string };\n\nfunction hostIsLittleEndian(): boolean {\n return new Uint8Array(new Uint16Array([1]).buffer)[0] === 1;\n}\n\nexport function abortedError(): ImageKernelExecutionError {\n return new ImageKernelExecutionError(\"aborted\", \"Image-kernel execution was aborted; no output is available.\");\n}\n\n/** Rejects when the signal aborts; the returned cleanup removes the listener. */\nfunction abortRace(signal: AbortSignal | undefined): { promise: Promise<never>; cleanup: () => void } {\n if (!signal) return { promise: new Promise<never>(() => undefined), cleanup: () => undefined };\n let cleanup = (): void => undefined;\n const promise = new Promise<never>((_, reject) => {\n if (signal.aborted) { reject(abortedError()); return; }\n const listener = (): void => reject(abortedError());\n signal.addEventListener(\"abort\", listener, { once: true });\n cleanup = (): void => signal.removeEventListener(\"abort\", listener);\n });\n promise.catch(() => undefined);\n return { promise, cleanup };\n}\n\n/**\n * Requests a device with high limits from `gpu` (normally `navigator.gpu`). It does not throw when\n * WebGPU is unavailable; the caller decides whether to fall back to the CPU or fail. An abort during\n * acquisition does throw.\n */\nexport async function acquireWebGpuRuntime(gpu: unknown, powerPreference: \"low-power\" | \"high-performance\" | undefined,\n signal: AbortSignal | undefined): Promise<WebGpuAcquisition> {\n if (!hostIsLittleEndian()) return { failure: \"unsupported-platform-endianness\", message: \"WebGPU buffers require a little-endian host.\" };\n const api = gpu as Partial<GPU> | null | undefined;\n if (!api || typeof api !== \"object\" || typeof api.requestAdapter !== \"function\") {\n return { failure: \"webgpu-unavailable\", message: \"WebGPU is not available in this runtime.\" };\n }\n const abort = abortRace(signal);\n try {\n let adapter: GPUAdapter | null;\n try {\n adapter = await Promise.race([api.requestAdapter(powerPreference ? { powerPreference } : undefined), abort.promise]);\n } catch (error) {\n if (error instanceof ImageKernelExecutionError) throw error;\n adapter = null;\n }\n if (!adapter) return { failure: \"adapter-unavailable\", message: \"No WebGPU adapter is available.\" };\n const adapterStorage = adapter.limits.maxStorageBufferBindingSize, adapterBuffer = adapter.limits.maxBufferSize;\n if (!(adapterStorage >= WEBGPU_MINIMUM_STORAGE_BINDING_BYTES && adapterBuffer >= WEBGPU_MINIMUM_STORAGE_BINDING_BYTES)) {\n return { failure: \"insufficient-limits\", message: \"The WebGPU adapter's storage-buffer limits are below the backend minimum.\" };\n }\n const storage = Math.min(adapterStorage, adapterBuffer, WEBGPU_REQUESTED_STORAGE_BINDING_BYTES);\n let device: GPUDevice, pending: Promise<GPUDevice> | undefined;\n try {\n pending = adapter.requestDevice({ label: \"photivra-image-kernels\",\n requiredLimits: { maxStorageBufferBindingSize: storage, maxBufferSize: storage } });\n device = await Promise.race([pending, abort.promise]);\n } catch (error) {\n if (error instanceof ImageKernelExecutionError) {\n // The abort won the race. A device that still arrives later is destroyed, so it never leaks.\n if (pending) void Promise.resolve(pending).then(late => late.destroy(), () => undefined);\n throw error;\n }\n return { failure: \"device-request-failed\", message: \"The WebGPU device request failed.\" };\n }\n if (signal?.aborted) { device.destroy(); throw abortedError(); }\n return { runtime: createRuntime(device, storage) };\n } finally {\n abort.cleanup();\n }\n}\n\nfunction createRuntime(device: GPUDevice, storage: number): WebGpuRuntime {\n let lost = false, destroyed = false;\n let rejectLost: (error: ImageKernelExecutionError) => void = () => undefined;\n const lostPromise = new Promise<never>((_, reject) => { rejectLost = reject; });\n lostPromise.catch(() => undefined);\n void device.lost.then(() => {\n lost = true;\n rejectLost(new ImageKernelExecutionError(\"device-lost\", \"The WebGPU device was lost; no output is available.\"));\n });\n // Errors are collected through error scopes; this only keeps uncaptured errors out of the console.\n device.onuncapturederror = (event: GPUUncapturedErrorEvent): void => { event.preventDefault(); };\n const maximumWorkgroupsPerDimension = device.limits.maxComputeWorkgroupsPerDimension;\n return {\n device,\n maximumStorageBindingBytes: Math.min(storage, device.limits.maxStorageBufferBindingSize, device.limits.maxBufferSize),\n maximumWorkgroupsPerDimension,\n isLost: (): boolean => lost,\n async guard<T>(promise: Promise<T>, signal: AbortSignal | undefined): Promise<T> {\n promise.catch(() => undefined);\n if (lost) throw new ImageKernelExecutionError(\"device-lost\", \"The WebGPU device was lost; no output is available.\");\n const abort = abortRace(signal);\n try { return await Promise.race([promise, lostPromise, abort.promise]); } finally { abort.cleanup(); }\n },\n destroy(): void { if (!destroyed) { destroyed = true; device.destroy(); } }\n };\n}\n\n/** Per-operation resource scope: every buffer is destroyed when the operation settles. */\nexport class GpuResourceScope {\n readonly #runtime: WebGpuRuntime;\n readonly #buffers: GPUBuffer[] = [];\n\n constructor(runtime: WebGpuRuntime) { this.#runtime = runtime; }\n\n buffer(label: string, size: number, usage: number): GPUBuffer {\n const buffer = this.#runtime.device.createBuffer({ label, size: Math.max(16, Math.ceil(size / 16) * 16), usage });\n this.#buffers.push(buffer);\n return buffer;\n }\n\n /** Storage buffer initialised from host data (padded to a 16-byte multiple). */\n upload(label: string, data: ArrayBufferView<ArrayBuffer>, usage: number): GPUBuffer {\n const buffer = this.buffer(label, data.byteLength, usage | BUFFER_USAGE.COPY_DST);\n if (data.byteLength > 0) this.#runtime.device.queue.writeBuffer(buffer, 0, data.buffer, data.byteOffset, data.byteLength);\n return buffer;\n }\n\n release(): void {\n for (const buffer of this.#buffers.splice(0)) buffer.destroy();\n }\n}\n\n/** Workgroup grid for a 1-D invocation count (2-D when it exceeds one dimension). */\nexport function linearDispatch(invocations: number, workgroupSize: number, maximumPerDimension: number): [number, number] {\n const groups = Math.max(1, Math.ceil(invocations / workgroupSize));\n const x = Math.min(groups, maximumPerDimension), y = Math.ceil(groups / x);\n if (y > maximumPerDimension) {\n throw new ImageKernelExecutionError(\"insufficient-limits\", \"Band exceeds the adapter's dispatch limits.\");\n }\n return [x, y];\n}\n\n/**\n * Submits one compute pass and copies `outputs` into mappable staging buffers, then maps them. Validation\n * and out-of-memory errors are captured with error scopes and reported as domain errors.\n */\nexport async function runComputePass(runtime: WebGpuRuntime, scope: GpuResourceScope, pipeline: GPUComputePipeline,\n bindGroup: GPUBindGroup, workgroups: readonly [number, number], outputs: readonly { buffer: GPUBuffer; bytes: number }[],\n signal: AbortSignal | undefined): Promise<ArrayBuffer[]> {\n const device = runtime.device;\n device.pushErrorScope(\"out-of-memory\");\n device.pushErrorScope(\"validation\");\n const staging = outputs.map(({ bytes }, i) =>\n scope.buffer(`photivra-readback-${i}`, bytes, BUFFER_USAGE.MAP_READ | BUFFER_USAGE.COPY_DST));\n const encoder = device.createCommandEncoder({ label: \"photivra-image-kernel\" });\n const pass = encoder.beginComputePass();\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, bindGroup);\n pass.dispatchWorkgroups(workgroups[0], workgroups[1]);\n pass.end();\n outputs.forEach(({ buffer }, i) => encoder.copyBufferToBuffer(buffer, 0, staging[i]!, 0, staging[i]!.size));\n device.queue.submit([encoder.finish()]);\n // Pop both scopes before any await so an abort or loss never leaves the device's scope stack unbalanced.\n const validationScope = device.popErrorScope(), memoryScope = device.popErrorScope();\n const validation = await runtime.guard(validationScope, signal);\n const memory = await runtime.guard(memoryScope, signal);\n if (memory) throw new ImageKernelExecutionError(\"out-of-memory\", \"The WebGPU device ran out of memory.\");\n if (validation) throw new ImageKernelExecutionError(\"gpu-validation\", \"WebGPU rejected an image-kernel command.\");\n const results: ArrayBuffer[] = [];\n for (let i = 0; i < staging.length; i++) {\n const buffer = staging[i]!;\n await runtime.guard(buffer.mapAsync(MAP_MODE_READ), signal);\n results.push(buffer.getMappedRange(0, Math.ceil(outputs[i]!.bytes / 4) * 4).slice(0));\n buffer.unmap();\n }\n return results;\n}\n\n/** Compiles a compute pipeline; compilation/validation failures are domain errors. */\nexport async function createComputePipeline(runtime: WebGpuRuntime, label: string, code: string,\n signal: AbortSignal | undefined): Promise<GPUComputePipeline> {\n const device = runtime.device;\n device.pushErrorScope(\"validation\");\n const module = device.createShaderModule({ label, code });\n const pending = device.createComputePipelineAsync({ label, layout: \"auto\", compute: { module, entryPoint: \"main\" } });\n const scope = device.popErrorScope();\n let pipeline: GPUComputePipeline;\n try {\n pipeline = await runtime.guard(pending, signal);\n } catch (error) {\n if (error instanceof ImageKernelExecutionError) throw error;\n throw new ImageKernelExecutionError(\"gpu-validation\", `WebGPU could not compile the ${label} kernel.`);\n }\n if (await runtime.guard(scope, signal)) {\n throw new ImageKernelExecutionError(\"gpu-validation\", `WebGPU could not compile the ${label} kernel.`);\n }\n return pipeline;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"webgpu-runtime.js","sourceRoot":"","sources":["../../src/gpu/webgpu-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Internal WebGPU device handling for the image-kernel accelerator: getting the adapter and device,\n * limits, tracking device loss, racing work against abort and loss, error scopes, banded buffers and\n * cleanup. Not exported from the package root. WebGPU types never appear in the published type\n * declarations, so consumers do not need WebGPU typings.\n */\nimport { ImageKernelExecutionError, type ImageKernelAdapterDescription, type ImageKernelFallbackReason } from \"./image-kernel-execution.js\";\n\n/** WebGPU spec constants (GPUBufferUsage, GPUMapMode), defined here so no global is needed at import time. */\nexport const BUFFER_USAGE = Object.freeze({ MAP_READ: 0x0001, COPY_SRC: 0x0004, COPY_DST: 0x0008, UNIFORM: 0x0040, STORAGE: 0x0080 });\nconst MAP_MODE_READ = 0x0001;\n\n/** Minimum per-binding storage this backend requires (the WebGPU default is 128 MiB). */\nexport const WEBGPU_MINIMUM_STORAGE_BINDING_BYTES = 16 * 1024 * 1024;\n/** Upper limit requested from the adapter, so one band never asks for more than this per binding. */\nexport const WEBGPU_REQUESTED_STORAGE_BINDING_BYTES = 1024 * 1024 * 1024;\n\nexport interface WebGpuRuntime {\n readonly device: GPUDevice;\n /** #481: the adapter's `info`, or null when the implementation has none. */\n readonly adapter: ImageKernelAdapterDescription | null;\n readonly maximumStorageBindingBytes: number;\n readonly maximumWorkgroupsPerDimension: number;\n /** Set once `device.lost` settles; every later wait rejects with `device-lost`. */\n isLost(): boolean;\n /** Races a GPU promise with device loss and the operation's abort signal. */\n guard<T>(promise: Promise<T>, signal: AbortSignal | undefined): Promise<T>;\n destroy(): void;\n}\n\nexport type WebGpuAcquisition = { runtime: WebGpuRuntime } | { failure: ImageKernelFallbackReason; message: string };\n\nfunction hostIsLittleEndian(): boolean {\n return new Uint8Array(new Uint16Array([1]).buffer)[0] === 1;\n}\n\nexport function abortedError(): ImageKernelExecutionError {\n return new ImageKernelExecutionError(\"aborted\", \"Image-kernel execution was aborted; no output is available.\");\n}\n\n/** Rejects when the signal aborts; the returned cleanup removes the listener. */\nfunction abortRace(signal: AbortSignal | undefined): { promise: Promise<never>; cleanup: () => void } {\n if (!signal) return { promise: new Promise<never>(() => undefined), cleanup: () => undefined };\n let cleanup = (): void => undefined;\n const promise = new Promise<never>((_, reject) => {\n if (signal.aborted) { reject(abortedError()); return; }\n const listener = (): void => reject(abortedError());\n signal.addEventListener(\"abort\", listener, { once: true });\n cleanup = (): void => signal.removeEventListener(\"abort\", listener);\n });\n promise.catch(() => undefined);\n return { promise, cleanup };\n}\n\n/**\n * Requests a device with high limits from `gpu` (normally `navigator.gpu`). It does not throw when\n * WebGPU is unavailable; the caller decides whether to fall back to the CPU or fail. An abort during\n * acquisition does throw.\n */\nexport async function acquireWebGpuRuntime(gpu: unknown, powerPreference: \"low-power\" | \"high-performance\" | undefined,\n signal: AbortSignal | undefined): Promise<WebGpuAcquisition> {\n if (!hostIsLittleEndian()) return { failure: \"unsupported-platform-endianness\", message: \"WebGPU buffers require a little-endian host.\" };\n const api = gpu as Partial<GPU> | null | undefined;\n if (!api || typeof api !== \"object\" || typeof api.requestAdapter !== \"function\") {\n return { failure: \"webgpu-unavailable\", message: \"WebGPU is not available in this runtime.\" };\n }\n const abort = abortRace(signal);\n try {\n let adapter: GPUAdapter | null;\n try {\n adapter = await Promise.race([api.requestAdapter(powerPreference ? { powerPreference } : undefined), abort.promise]);\n } catch (error) {\n if (error instanceof ImageKernelExecutionError) throw error;\n adapter = null;\n }\n if (!adapter) return { failure: \"adapter-unavailable\", message: \"No WebGPU adapter is available.\" };\n const adapterStorage = adapter.limits.maxStorageBufferBindingSize, adapterBuffer = adapter.limits.maxBufferSize;\n if (!(adapterStorage >= WEBGPU_MINIMUM_STORAGE_BINDING_BYTES && adapterBuffer >= WEBGPU_MINIMUM_STORAGE_BINDING_BYTES)) {\n return { failure: \"insufficient-limits\", message: \"The WebGPU adapter's storage-buffer limits are below the backend minimum.\" };\n }\n const storage = Math.min(adapterStorage, adapterBuffer, WEBGPU_REQUESTED_STORAGE_BINDING_BYTES);\n let device: GPUDevice, pending: Promise<GPUDevice> | undefined;\n try {\n pending = adapter.requestDevice({ label: \"photivra-image-kernels\",\n requiredLimits: { maxStorageBufferBindingSize: storage, maxBufferSize: storage } });\n device = await Promise.race([pending, abort.promise]);\n } catch (error) {\n if (error instanceof ImageKernelExecutionError) {\n // The abort won the race. A device that still arrives later is destroyed, so it never leaks.\n if (pending) void Promise.resolve(pending).then(late => late.destroy(), () => undefined);\n throw error;\n }\n return { failure: \"device-request-failed\", message: \"The WebGPU device request failed.\" };\n }\n if (signal?.aborted) { device.destroy(); throw abortedError(); }\n return { runtime: createRuntime(device, storage, describeAdapter(adapter)) };\n } finally {\n abort.cleanup();\n }\n}\n\n/** `GPUAdapter.info` as plain strings (missing or non-string fields read as empty), or null when the adapter has no `info`. */\nfunction describeAdapter(adapter: GPUAdapter): ImageKernelAdapterDescription | null {\n const info = (adapter as { info?: Partial<Record<keyof ImageKernelAdapterDescription, unknown>> | null }).info;\n if (!info || typeof info !== \"object\") return null;\n const text = (value: unknown): string => (typeof value === \"string\" ? value : \"\");\n return { vendor: text(info.vendor), architecture: text(info.architecture), device: text(info.device), description: text(info.description) };\n}\n\nfunction createRuntime(device: GPUDevice, storage: number, adapter: ImageKernelAdapterDescription | null): WebGpuRuntime {\n let lost = false, destroyed = false;\n let rejectLost: (error: ImageKernelExecutionError) => void = () => undefined;\n const lostPromise = new Promise<never>((_, reject) => { rejectLost = reject; });\n lostPromise.catch(() => undefined);\n void device.lost.then(() => {\n lost = true;\n rejectLost(new ImageKernelExecutionError(\"device-lost\", \"The WebGPU device was lost; no output is available.\"));\n });\n // Errors are collected through error scopes; this only keeps uncaptured errors out of the console.\n device.onuncapturederror = (event: GPUUncapturedErrorEvent): void => { event.preventDefault(); };\n const maximumWorkgroupsPerDimension = device.limits.maxComputeWorkgroupsPerDimension;\n return {\n device, adapter,\n maximumStorageBindingBytes: Math.min(storage, device.limits.maxStorageBufferBindingSize, device.limits.maxBufferSize),\n maximumWorkgroupsPerDimension,\n isLost: (): boolean => lost,\n async guard<T>(promise: Promise<T>, signal: AbortSignal | undefined): Promise<T> {\n promise.catch(() => undefined);\n if (lost) throw new ImageKernelExecutionError(\"device-lost\", \"The WebGPU device was lost; no output is available.\");\n const abort = abortRace(signal);\n try { return await Promise.race([promise, lostPromise, abort.promise]); } finally { abort.cleanup(); }\n },\n destroy(): void { if (!destroyed) { destroyed = true; device.destroy(); } }\n };\n}\n\n/** Per-operation resource scope: every buffer is destroyed when the operation settles. */\nexport class GpuResourceScope {\n readonly #runtime: WebGpuRuntime;\n readonly #buffers: GPUBuffer[] = [];\n\n constructor(runtime: WebGpuRuntime) { this.#runtime = runtime; }\n\n buffer(label: string, size: number, usage: number): GPUBuffer {\n const buffer = this.#runtime.device.createBuffer({ label, size: Math.max(16, Math.ceil(size / 16) * 16), usage });\n this.#buffers.push(buffer);\n return buffer;\n }\n\n /** Storage buffer initialised from host data (padded to a 16-byte multiple). */\n upload(label: string, data: ArrayBufferView<ArrayBuffer>, usage: number): GPUBuffer {\n const buffer = this.buffer(label, data.byteLength, usage | BUFFER_USAGE.COPY_DST);\n if (data.byteLength > 0) this.#runtime.device.queue.writeBuffer(buffer, 0, data.buffer, data.byteOffset, data.byteLength);\n return buffer;\n }\n\n release(): void {\n for (const buffer of this.#buffers.splice(0)) buffer.destroy();\n }\n}\n\n/** Workgroup grid for a 1-D invocation count (2-D when it exceeds one dimension). */\nexport function linearDispatch(invocations: number, workgroupSize: number, maximumPerDimension: number): [number, number] {\n const groups = Math.max(1, Math.ceil(invocations / workgroupSize));\n const x = Math.min(groups, maximumPerDimension), y = Math.ceil(groups / x);\n if (y > maximumPerDimension) {\n throw new ImageKernelExecutionError(\"insufficient-limits\", \"Band exceeds the adapter's dispatch limits.\");\n }\n return [x, y];\n}\n\n/**\n * Submits one compute pass and copies `outputs` into mappable staging buffers, then maps them. Validation\n * and out-of-memory errors are captured with error scopes and reported as domain errors.\n */\nexport async function runComputePass(runtime: WebGpuRuntime, scope: GpuResourceScope, pipeline: GPUComputePipeline,\n bindGroup: GPUBindGroup | readonly GPUBindGroup[], workgroups: readonly [number, number], outputs: readonly { buffer: GPUBuffer; bytes: number }[],\n signal: AbortSignal | undefined): Promise<ArrayBuffer[]> {\n const device = runtime.device;\n device.pushErrorScope(\"out-of-memory\");\n device.pushErrorScope(\"validation\");\n const staging = outputs.map(({ bytes }, i) =>\n scope.buffer(`photivra-readback-${i}`, bytes, BUFFER_USAGE.MAP_READ | BUFFER_USAGE.COPY_DST));\n const encoder = device.createCommandEncoder({ label: \"photivra-image-kernel\" });\n const pass = encoder.beginComputePass();\n pass.setPipeline(pipeline);\n // One bind group at index 0, or several at indices 0, 1, … (the display-view kernel binds its material module at 1).\n (Array.isArray(bindGroup) ? bindGroup as readonly GPUBindGroup[] : [bindGroup as GPUBindGroup]).forEach((group, index) => pass.setBindGroup(index, group));\n pass.dispatchWorkgroups(workgroups[0], workgroups[1]);\n pass.end();\n outputs.forEach(({ buffer }, i) => encoder.copyBufferToBuffer(buffer, 0, staging[i]!, 0, staging[i]!.size));\n device.queue.submit([encoder.finish()]);\n // Pop both scopes before any await so an abort or loss never leaves the device's scope stack unbalanced.\n const validationScope = device.popErrorScope(), memoryScope = device.popErrorScope();\n const validation = await runtime.guard(validationScope, signal);\n const memory = await runtime.guard(memoryScope, signal);\n if (memory) throw new ImageKernelExecutionError(\"out-of-memory\", \"The WebGPU device ran out of memory.\");\n if (validation) throw new ImageKernelExecutionError(\"gpu-validation\", \"WebGPU rejected an image-kernel command.\");\n const results: ArrayBuffer[] = [];\n for (let i = 0; i < staging.length; i++) {\n const buffer = staging[i]!;\n await runtime.guard(buffer.mapAsync(MAP_MODE_READ), signal);\n results.push(buffer.getMappedRange(0, Math.ceil(outputs[i]!.bytes / 4) * 4).slice(0));\n buffer.unmap();\n }\n return results;\n}\n\n/** Compiles a compute pipeline; compilation/validation failures are domain errors. */\nexport async function createComputePipeline(runtime: WebGpuRuntime, label: string, code: string,\n signal: AbortSignal | undefined): Promise<GPUComputePipeline> {\n const device = runtime.device;\n device.pushErrorScope(\"validation\");\n const module = device.createShaderModule({ label, code });\n const pending = device.createComputePipelineAsync({ label, layout: \"auto\", compute: { module, entryPoint: \"main\" } });\n const scope = device.popErrorScope();\n let pipeline: GPUComputePipeline;\n try {\n pipeline = await runtime.guard(pending, signal);\n } catch (error) {\n if (error instanceof ImageKernelExecutionError) throw error;\n throw new ImageKernelExecutionError(\"gpu-validation\", `WebGPU could not compile the ${label} kernel.`);\n }\n if (await runtime.guard(scope, signal)) {\n throw new ImageKernelExecutionError(\"gpu-validation\", `WebGPU could not compile the ${label} kernel.`);\n }\n return pipeline;\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Whether this realm may use WebGPU when a caller asks for it. */
|
|
2
|
+
export declare function getWebGpuEnabled(): boolean;
|
|
3
|
+
/** Turns WebGPU on (`true`, the default) or off (`false`) for this realm. Anything but a boolean is refused. */
|
|
4
|
+
export declare function setWebGpuEnabled(enabled: boolean): void;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/**
|
|
3
|
+
* One switch for every GPU path in the engine (#474). The GPU is opt-in per call: nothing runs on WebGPU
|
|
4
|
+
* unless a caller asks for the `webgpu-f32` backend. This switch is the veto a developer flips to keep the
|
|
5
|
+
* whole engine on the float64 CPU reference regardless of what callers ask, for example while debugging,
|
|
6
|
+
* measuring or reproducing a result.
|
|
7
|
+
*
|
|
8
|
+
* - `true` (the default) lets a request for `webgpu-f32` go ahead.
|
|
9
|
+
* - `false` makes every such request behave as if WebGPU were unavailable: with `fallback: "cpu-reference"`
|
|
10
|
+
* the reference runs and the result's label says `fallbackReason: "webgpu-disabled"`; with `fallback: "fail"`
|
|
11
|
+
* the request throws an `ImageKernelExecutionError` with that reason.
|
|
12
|
+
*
|
|
13
|
+
* The switch is per JavaScript realm: a Web Worker has its own, and a page's setting does not reach its
|
|
14
|
+
* workers. Flipping it never changes a result that has already been computed; accelerators created while the
|
|
15
|
+
* switch was on keep their device until they are disposed.
|
|
16
|
+
*/
|
|
17
|
+
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
18
|
+
let webGpuEnabled = true;
|
|
19
|
+
/** Whether this realm may use WebGPU when a caller asks for it. */
|
|
20
|
+
export function getWebGpuEnabled() {
|
|
21
|
+
return webGpuEnabled;
|
|
22
|
+
}
|
|
23
|
+
/** Turns WebGPU on (`true`, the default) or off (`false`) for this realm. Anything but a boolean is refused. */
|
|
24
|
+
export function setWebGpuEnabled(enabled) {
|
|
25
|
+
if (typeof enabled !== "boolean")
|
|
26
|
+
throw new InvalidConfigurationError("setWebGpuEnabled expects a boolean.");
|
|
27
|
+
webGpuEnabled = enabled;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=webgpu-switch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webgpu-switch.js","sourceRoot":"","sources":["../../src/gpu/webgpu-switch.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAE3E,IAAI,aAAa,GAAG,IAAI,CAAC;AAEzB,mEAAmE;AACnE,MAAM,UAAU,gBAAgB;IAC9B,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,gHAAgH;AAChH,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,IAAI,OAAO,OAAO,KAAK,SAAS;QAAE,MAAM,IAAI,yBAAyB,CAAC,qCAAqC,CAAC,CAAC;IAC7G,aAAa,GAAG,OAAO,CAAC;AAC1B,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * One switch for every GPU path in the engine (#474). The GPU is opt-in per call: nothing runs on WebGPU\n * unless a caller asks for the `webgpu-f32` backend. This switch is the veto a developer flips to keep the\n * whole engine on the float64 CPU reference regardless of what callers ask, for example while debugging,\n * measuring or reproducing a result.\n *\n * - `true` (the default) lets a request for `webgpu-f32` go ahead.\n * - `false` makes every such request behave as if WebGPU were unavailable: with `fallback: \"cpu-reference\"`\n * the reference runs and the result's label says `fallbackReason: \"webgpu-disabled\"`; with `fallback: \"fail\"`\n * the request throws an `ImageKernelExecutionError` with that reason.\n *\n * The switch is per JavaScript realm: a Web Worker has its own, and a page's setting does not reach its\n * workers. Flipping it never changes a result that has already been computed; accelerators created while the\n * switch was on keep their device until they are disposed.\n */\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\n\nlet webGpuEnabled = true;\n\n/** Whether this realm may use WebGPU when a caller asks for it. */\nexport function getWebGpuEnabled(): boolean {\n return webGpuEnabled;\n}\n\n/** Turns WebGPU on (`true`, the default) or off (`false`) for this realm. Anything but a boolean is refused. */\nexport function setWebGpuEnabled(enabled: boolean): void {\n if (typeof enabled !== \"boolean\") throw new InvalidConfigurationError(\"setWebGpuEnabled expects a boolean.\");\n webGpuEnabled = enabled;\n}\n"]}
|