@photivra/engine 2.12.0 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +144 -1
- package/CITATION.cff +1 -1
- package/README.md +7 -7
- package/SECURITY.md +1 -1
- package/THIRD_PARTY.md +3 -0
- package/dist/camera/lens-projection.js +2 -1
- package/dist/camera/lens-projection.js.map +1 -1
- package/dist/capture/dng-import.js +1 -1
- package/dist/capture/dng-import.js.map +1 -1
- package/dist/capture/export-jpeg.d.ts +1 -1
- package/dist/capture/export-jpeg.js +6 -4
- package/dist/capture/export-jpeg.js.map +1 -1
- package/dist/capture/host-yield-cadence.js +1 -1
- package/dist/capture/host-yield-cadence.js.map +1 -1
- package/dist/capture/native-environment-optical-stage.js +1 -1
- package/dist/capture/native-environment-optical-stage.js.map +1 -1
- package/dist/capture/native-raw.js +1 -1
- package/dist/capture/native-raw.js.map +1 -1
- package/dist/capture/packed-sensor-raw.js +3 -3
- package/dist/capture/packed-sensor-raw.js.map +1 -1
- package/dist/capture/sensor-raw-producer.js +1 -1
- package/dist/capture/sensor-raw-producer.js.map +1 -1
- package/dist/color/capture-color.js +3 -3
- package/dist/color/capture-color.js.map +1 -1
- package/dist/color/chromatic-adaptation.js +2 -2
- package/dist/color/chromatic-adaptation.js.map +1 -1
- package/dist/color/color-matching-functions.js +1 -1
- package/dist/color/color-matching-functions.js.map +1 -1
- package/dist/color/colorimetry-math.js +2 -2
- package/dist/color/colorimetry-math.js.map +1 -1
- package/dist/color/illuminants.js +3 -3
- package/dist/color/illuminants.js.map +1 -1
- package/dist/color/rgb-color-spaces.js +1 -1
- package/dist/color/rgb-color-spaces.js.map +1 -1
- package/dist/color/sensor-color-development.js +1 -1
- package/dist/color/sensor-color-development.js.map +1 -1
- package/dist/core/record-validation.js +3 -3
- package/dist/core/record-validation.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/equipment/generic-prime-lenses.js +3 -3
- package/dist/equipment/generic-prime-lenses.js.map +1 -1
- package/dist/equipment/generic-tier-assets.d.ts +23 -1
- package/dist/equipment/generic-tier-assets.js +58 -30
- package/dist/equipment/generic-tier-assets.js.map +1 -1
- package/dist/equipment/generic-tier-presets.d.ts +6 -3
- package/dist/equipment/generic-tier-presets.js +26 -13
- package/dist/equipment/generic-tier-presets.js.map +1 -1
- package/dist/exposure/auto-iso-slowest-shutter.d.ts +120 -0
- package/dist/exposure/auto-iso-slowest-shutter.js +217 -0
- package/dist/exposure/auto-iso-slowest-shutter.js.map +1 -0
- package/dist/exposure/exposure-mode-resolver.d.ts +57 -1
- package/dist/exposure/exposure-mode-resolver.js +238 -33
- package/dist/exposure/exposure-mode-resolver.js.map +1 -1
- package/dist/exposure/flash-ttl.js +1 -1
- package/dist/exposure/flash-ttl.js.map +1 -1
- package/dist/exposure/flash.js +1 -1
- package/dist/exposure/flash.js.map +1 -1
- package/dist/facade/chart-material-layers.js +2 -2
- package/dist/facade/chart-material-layers.js.map +1 -1
- package/dist/facade/chart-radiance-batch.js +1 -1
- package/dist/facade/chart-radiance-batch.js.map +1 -1
- package/dist/facade/chart-scenes.d.ts +45 -8
- package/dist/facade/chart-scenes.js +101 -44
- package/dist/facade/chart-scenes.js.map +1 -1
- package/dist/facade/color-patches.d.ts +129 -0
- package/dist/facade/color-patches.js +209 -0
- package/dist/facade/color-patches.js.map +1 -0
- package/dist/facade/diffraction-provider.js +12 -13
- package/dist/facade/diffraction-provider.js.map +1 -1
- package/dist/facade/display-view-gpu.js +1 -1
- package/dist/facade/display-view-gpu.js.map +1 -1
- package/dist/facade/display-view.d.ts +27 -0
- package/dist/facade/display-view.js +234 -65
- package/dist/facade/display-view.js.map +1 -1
- package/dist/facade/scene-radiance.js +2 -2
- package/dist/facade/scene-radiance.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +139 -12
- package/dist/facade/simulate-capture.js +209 -36
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/facade/simulate-display-view.js +2 -2
- package/dist/facade/simulate-display-view.js.map +1 -1
- package/dist/gpu/chart-composite-gpu.js +2 -2
- package/dist/gpu/chart-composite-gpu.js.map +1 -1
- package/dist/gpu/display-view-composite-material-module.js +1 -1
- package/dist/gpu/display-view-composite-material-module.js.map +1 -1
- package/dist/gpu/display-view-quality-gpu.d.ts +2 -1
- package/dist/gpu/display-view-quality-gpu.js +24 -14
- package/dist/gpu/display-view-quality-gpu.js.map +1 -1
- package/dist/gpu/image-kernel-execution.js +2 -2
- package/dist/gpu/image-kernel-execution.js.map +1 -1
- package/dist/gpu/temporal-sum-gpu.js +23 -23
- package/dist/gpu/webgpu-runtime.js +1 -1
- package/dist/gpu/webgpu-runtime.js.map +1 -1
- package/dist/gpu/wgsl-chart-composite-kernel.js +318 -318
- package/dist/gpu/wgsl-chart-composite-kernel.js.map +1 -1
- package/dist/gpu/wgsl-chart-kernel.js +117 -117
- package/dist/gpu/wgsl-chart-kernel.js.map +1 -1
- package/dist/gpu/wgsl-display-view-quality-kernel.d.ts +13 -1
- package/dist/gpu/wgsl-display-view-quality-kernel.js +522 -488
- package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -1
- package/dist/gpu/wgsl-display-view-speed-kernel.js +248 -248
- package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -1
- package/dist/gpu/wgsl-kernels.js +203 -203
- package/dist/gpu/wgsl-kernels.js.map +1 -1
- package/dist/gpu/wgsl-sensor-kernel.js +302 -302
- package/dist/gpu/wgsl-sensor-kernel.js.map +1 -1
- package/dist/index.d.ts +8 -5
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/motion/temporal-exposure-sum.js +1 -1
- package/dist/motion/temporal-exposure-sum.js.map +1 -1
- package/dist/optics/diffraction-psf-profile.js +4 -4
- package/dist/optics/diffraction-psf-profile.js.map +1 -1
- package/dist/optics/front-of-lens-filter.js +1 -1
- package/dist/optics/front-of-lens-filter.js.map +1 -1
- package/dist/optics/irradiance-convolution.d.ts +10 -0
- package/dist/optics/irradiance-convolution.js +49 -14
- package/dist/optics/irradiance-convolution.js.map +1 -1
- package/dist/output/native-capture-sdr.js +1 -1
- package/dist/output/native-capture-sdr.js.map +1 -1
- package/dist/output/png-encoder.js +2 -2
- package/dist/output/png-encoder.js.map +1 -1
- package/dist/output/print-jpeg.js +13 -10
- package/dist/output/print-jpeg.js.map +1 -1
- package/dist/output/text-metadata.d.ts +22 -2
- package/dist/output/text-metadata.js +58 -9
- package/dist/output/text-metadata.js.map +1 -1
- package/dist/sensor/fixed-pattern-noise.js +1 -1
- package/dist/sensor/fixed-pattern-noise.js.map +1 -1
- package/dist/sensor/readout-exposure-linkage.js +1 -1
- package/dist/sensor/readout-exposure-linkage.js.map +1 -1
- package/docs/API_REFERENCE.md +49 -1
- package/docs/QUICK_START.md +104 -9
- package/docs/USAGE.md +241 -2
- package/docs/api/core-version.md +1 -1
- package/docs/api/equipment-generic-tier-assets.md +41 -1
- package/docs/api/equipment-generic-tier-presets.md +11 -3
- package/docs/api/exports.json +172 -2
- package/docs/api/exposure-auto-iso-slowest-shutter.md +139 -0
- package/docs/api/exposure-exposure-mode-resolver.md +68 -0
- package/docs/api/facade-chart-scenes.md +36 -5
- package/docs/api/facade-color-patches.md +150 -0
- package/docs/api/facade-simulate-capture.md +140 -9
- package/docs/api/output-text-metadata.md +34 -0
- package/llms.txt +1 -0
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diffraction-provider.js","sourceRoot":"","sources":["../../src/facade/diffraction-provider.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Fast execution of `simulateCapture`'s `lens.diffraction` (2.1): an object-space convolution in the scene\n * provider, instead of one scene query per PSF tap in the environment PSF quadrature.\n *\n * The environment quadrature computes, at each site centre q and spectral node λ,\n * E(q, λ) = Σ_k K_λ(k)·T·L(s_k(q), λ),\n * where s_k(q) is the tap's source point (`sensorPsfSourcePoint`), L the scene radiance at the plane point\n * that source point sees, and T the radiance-to-irradiance factor. For the facade's planar scene seen\n * through the ideal rectilinear projection with a still camera and no lens field mapping, field throughput or\n * pupil rays:\n * - T is the same at every sensor point (paraxial π/(4·N_w²), no cos⁴ term), and\n * - with the kernel sampled on the site pitch, every source point is the centre of another site, so the plane\n * points form one regular lattice: u = (i + ½ − W/2)·2/w, v = −(j + ½ − H/2)·2/w (frame units, native\n * site (i, j), W×H native sites, w output width).\n * So E(q, λ) = T·B(q, λ) with B = K_λ ⊛ L sampled on that lattice: the same sum, in a different floating-point\n * order. B is computed once per spectral node with the engine's isoplanatic convolution\n * (`calculateIrradianceConvolution`, kernels from `resolveLensPsfConvolutionKernels`, exact site sampling) over a\n * grid that holds every source (the native raster plus the kernel radius on each side), in row bands. The\n * provider then answers each site-centre query with B instead of L, and the environment request declares no\n * PSF. Incoherent imaging is a linear superposition of intensity PSFs, so convolving radiance on the object\n * plane and convolving irradiance on the image plane agree for a planar object and a space-invariant PSF\n * (MIT OpenCourseWare 2.71, lecture 22, free; also see: Goodman, Introduction to Fourier Optics, 4th ed., §7.1).\n *\n * With an anti-aliasing point-splitting filter (2.1, `sensor.antiAliasing`) the environment queries the PSF taps\n * around each pre-filter source point q − a (a = a split offset) instead of around q. Those taps lie on the site\n * lattice shifted by a, so the same argument holds on each shifted lattice: B is computed once per distinct\n * fractional shift (offsets that differ by whole sites share one lattice; the centred four-spot filter with a\n * one-site separation needs a single half-site-shifted lattice) over the native raster widened by the largest\n * offset, and the environment's spatial quadrature still forms the weighted split sum.\n *\n * Region renders (2.6, `window`): only the lattice rows and columns that the region's sites can query (the window\n * plus the largest offset on each side) are convolved, over a grid that adds the kernel radius on each side. Every\n * output value is the same gather as in the whole render: the grid always holds every tap of every value it keeps\n * (real scene radiance out to the kernel radius, never a truncated edge), the single kernel patch does not depend on\n * the grid's origin, and `convolveIrradianceRows` sums each value in a fixed tap order (v outer, u inner). Narrowing\n * the grid therefore removes only values that no query reads, and the kept values are bit-identical.\n *\n * A query that does not land on one of the lattices (within 1e-6 site) is refused rather than approximated: the\n * facade uses this path only when the lattice argument above holds. A query outside the window is refused too.\n *\n * Defocus (#492, `lens.defocus`): the same argument holds for any space-invariant kernel on the site lattice, so the facade\n * passes `siteKernels` instead (the geometric defocus disc, or each node's diffraction kernel convolved with it). Their radius\n * may exceed the public 32-site convolution limit, so this path does not call `calculateIrradianceConvolution`: it checks the\n * samples and the kernel sums as that function does and gathers only the band's own values (`gatherInterior`), each summed\n * over the taps in the same fixed order (v outer, u inner, ascending; zero taps skipped, which adds exact zeros only). It\n * does not compute the 2R grid rows above and below a band that `calculateIrradianceConvolution` would also return (#419).\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { isInternalSceneRadianceEvaluator, markInternalSceneRadianceEvaluator, registerInternalRadianceAccess } from \"../core/internal-radiance-evaluator.js\";\nimport type { SceneRadianceEvaluationRequest, SceneRadianceEvaluationResult } from \"../schema/scene-radiance.js\";\nimport { createIrradianceConvolutionRunner } from \"../optics/irradiance-convolution.js\";\nimport { siteDiffractionKernel } from \"../optics/site-diffraction-kernel.js\";\nimport type { ResolveLensSampledPsfInput } from \"../optics/lens-psf-profile.js\";\nimport type { PlanarSceneRadianceProvider } from \"./scene-radiance.js\";\n\n/** Rows of native sites per convolution band, and the bands kept. Banding changes memory only, never values. */\nconst BAND_ROWS = 32;\nconst CACHED_BANDS = 4;\nconst LATTICE_TOLERANCE_SITES = 1e-6;\n\nexport interface DiffractedPlanarProviderInput {\n base: PlanarSceneRadianceProvider;\n /** The optical state of the sampled PSF, as for `resolveLensSampledPsf`, without field point and wavelength. Unused with `siteKernels`. */\n psf?: Omit<ResolveLensSampledPsfInput, \"fieldPointMm\" | \"wavelengthNm\">;\n /**\n * #492: the kernel of each spectral node on the site lattice, (2·kernelRadius + 1)² taps in row-major order, applied\n * instead of the diffraction kernels of `psf` (the defocus disc, or each node's diffraction kernel convolved with it).\n * Any radius; each kernel's sum may not exceed 1 + 2^-20.\n */\n siteKernels?: (wavelengthNm: number) => Float64Array;\n /** Spectral nodes the environment queries (the profile's wavelength nodes). */\n wavelengthsNm: readonly number[];\n kernelRadius: number;\n nativeWidth: number;\n nativeHeight: number;\n /** Output (active) width in sites: frame units are 2/outputWidth per site. */\n outputWidth: number;\n sitePitchMicrometers: number;\n /** Planar geometry of the base provider, to map query directions to plane points exactly as it does. */\n distanceM: number;\n metresPerFrameUnit: number;\n /**\n * Offsets of the query points from the site centres, in sites (+x right, +y down): the anti-aliasing split\n * offsets with their sign reversed (the environment queries q − a). Default: one zero offset.\n */\n queryOffsetsSites?: readonly { x: number; y: number }[];\n /**\n * Region renders (2.6): the native sites that will be queried (x, y, width, height in the native raster). Only the\n * lattice they can reach is convolved; values are bit-identical to the whole render's. Default: the whole raster.\n */\n window?: { x: number; y: number; width: number; height: number };\n /** Called with the duration in ms of each band convolution (diagnostics only; never changes values). */\n onConvolution?: (milliseconds: number) => void;\n}\n\n/** Internal (not exported from the package): the base provider with diffraction applied as an object-space convolution. */\nexport function createDiffractedPlanarProvider(input: DiffractedPlanarProviderInput): PlanarSceneRadianceProvider {\n const { base, wavelengthsNm, nativeWidth: W, nativeHeight: H, kernelRadius: R } = input;\n const g = 2 / input.outputWidth, pitch = input.sitePitchMicrometers;\n const index = new Map(wavelengthsNm.map((nm, i) => [nm, i]));\n // One lattice per distinct fractional query offset; M extra sites per side hold the offset queries.\n const offsets = input.queryOffsetsSites ?? [{ x: 0, y: 0 }];\n const fraction = (value: number): number => { const f = value - Math.floor(value); return f > 1 - LATTICE_TOLERANCE_SITES ? 0 : f < LATTICE_TOLERANCE_SITES ? 0 : f; };\n const shifts: { x: number; y: number }[] = [];\n for (const o of offsets) {\n const f = { x: fraction(o.x), y: fraction(o.y) };\n if (!shifts.some((s) => Math.abs(s.x - f.x) <= LATTICE_TOLERANCE_SITES && Math.abs(s.y - f.y) <= LATTICE_TOLERANCE_SITES)) shifts.push(f);\n }\n const M = Math.max(0, ...offsets.map((o) => Math.ceil(Math.max(Math.abs(o.x), Math.abs(o.y)) - LATTICE_TOLERANCE_SITES)));\n const LW = W + 2 * M, LH = H + 2 * M;\n // Lattice window (indices i + M, j + M): the sites the region queries plus the largest offset on each side, clipped\n // to the lattice. A site i queries i + floor(offset), and floor(offset) lies in [-M, M].\n const win = input.window ?? { x: 0, y: 0, width: W, height: H };\n const lx0 = Math.max(0, win.x), lx1 = Math.min(LW, win.x + win.width + 2 * M);\n const ly0 = Math.max(0, win.y), ly1 = Math.min(LH, win.y + win.height + 2 * M);\n if (!(lx0 < lx1 && ly0 < ly1)) throw new InvalidConfigurationError(\"Diffraction window must overlap the native raster.\");\n const NW = lx1 - lx0;\n // One kernel per wavelength, on the site grid, from the engine's own tap-to-site mapping (field point 0, 0); kept across calls.\n const siteKernels = input.siteKernels;\n if (!siteKernels && !input.psf) throw new InvalidConfigurationError(\"The object-space convolution needs a PSF or site kernels.\");\n const kernels = wavelengthsNm.map((wavelengthNm) => siteKernels ? checkedSiteKernel(siteKernels(wavelengthNm), R) :\n siteDiffractionKernel(input.psf!, wavelengthNm, pitch, R, \"Diffraction kernels must sample the site pitch exactly.\"));\n // #492: each site kernel's non-zero taps as grid offsets, in the gather's order.\n const taps = siteKernels ? kernels.map((kernel) => kernelTaps(kernel, R, NW + 2 * R)) : [];\n const gridWidth = NW + 2 * R;\n const now = (): number => globalThis.performance?.now() ?? Date.now();\n const bands = new Map<number, Float64Array[][]>();\n const materialAt = base.chartMaterialAt?.bind(base), materialRadiance = base.materialRadiance?.bind(base);\n function band(b: number): Float64Array[][] {\n const cached = bands.get(b);\n if (cached) { bands.delete(b); bands.set(b, cached); return cached; }\n const started = input.onConvolution ? now() : 0;\n const y0 = ly0 + b * BAND_ROWS, rows = Math.min(BAND_ROWS, ly1 - y0), gridHeight = rows + 2 * R, size = gridWidth * gridHeight;\n // #453: the band's shifts × spectral nodes convolutions share one geometry, validated once (the first runs the full\n // calculateIrradianceConvolution; every later one still checks its samples and kernel).\n const convolve = siteKernels ? undefined : createIrradianceConvolutionRunner({ schemaVersion: \"0.1.0\", width: gridWidth, height: gridHeight, kernelRadius: R,\n patchWidth: gridWidth, patchHeight: gridHeight, boundary: \"zero-outside-grid\" });\n const values = shifts.map((shift) => {\n // The plane point of lattice grid sample (gx, gy) of this shift, the same expressions for both fills below.\n const vOf = (gy: number): number => shift.y === 0 ? -(y0 + gy - R - M + 0.5 - H / 2) * g : -(y0 + gy - R - M + 0.5 + shift.y - H / 2) * g;\n const uOf = (x: number): number => shift.x === 0 ? (x - R - M + 0.5 - W / 2) * g : (x - R - M + 0.5 + shift.x - W / 2) * g;\n // #453, material scenes (chart presets and caller material scenes): radianceAt(u, v, nm) is materialRadiance(chartMaterialAt(u, v), nm)\n // (scene-radiance.ts), so the material is looked up once per lattice point and each node's samples come from one\n // materialRadiance per material present, the same numbers as one radianceAt per point and node.\n let materialOf: Int32Array | undefined;\n if (materialAt && materialRadiance) {\n materialOf = new Int32Array(size);\n for (let gy = 0; gy < gridHeight; gy++) {\n const v = vOf(gy);\n for (let gx = 0, x = lx0; gx < gridWidth; gx++, x++) materialOf[gy * gridWidth + gx] = materialAt(uOf(x), v);\n }\n }\n return wavelengthsNm.map((nm, w) => {\n const samples = new Float64Array(size);\n if (materialOf) {\n const radiance = new Map<number, number>();\n for (let i = 0; i < size; i++) {\n const m = materialOf[i]!;\n let value = radiance.get(m);\n if (value === undefined) { value = materialRadiance!(m, nm); radiance.set(m, value); }\n samples[i] = value;\n }\n } else {\n for (let gy = 0; gy < gridHeight; gy++) {\n const v = vOf(gy);\n for (let gx = 0, x = lx0; gx < gridWidth; gx++, x++) samples[gy * gridWidth + gx] = base.radianceAt(uOf(x), v, nm);\n }\n }\n if (!convolve) return gatherInterior(samples, taps[w]!, gridWidth, NW, rows, R);\n const blurred = convolve(samples, kernels[w]!);\n const out = new Float64Array(NW * rows);\n for (let y = 0; y < rows; y++) out.set(blurred.subarray((y + R) * gridWidth + R, (y + R) * gridWidth + R + NW), y * NW);\n return out;\n });\n });\n bands.set(b, values);\n if (bands.size > CACHED_BANDS) bands.delete(bands.keys().next().value!);\n if (input.onConvolution) input.onConvolution(now() - started);\n return values;\n }\n function blurredAt(u: number, v: number, nm: number): number {\n const w = index.get(nm), fi = u / g - 0.5 + W / 2, fj = -v / g - 0.5 + H / 2;\n if (w !== undefined) for (let s = 0; s < shifts.length; s++) {\n const shift = shifts[s]!, i = Math.round(fi - shift.x), j = Math.round(fj - shift.y);\n if (Math.abs(fi - shift.x - i) > LATTICE_TOLERANCE_SITES || Math.abs(fj - shift.y - j) > LATTICE_TOLERANCE_SITES) continue;\n const li = i + M, lj = j + M;\n if (li < lx0 || lj < ly0 || li >= lx1 || lj >= ly1) break;\n return band(Math.floor((lj - ly0) / BAND_ROWS))[s]![w]![((lj - ly0) % BAND_ROWS) * NW + li - lx0]!;\n }\n throw new InvalidConfigurationError(\"Diffraction query is off the site lattice; the object-space convolution does not apply.\");\n }\n const scale = input.metresPerFrameUnit, distance = input.distanceM, baseEvaluate = base.evaluateRadiance;\n const evaluateRadiance = (request: Readonly<SceneRadianceEvaluationRequest>): SceneRadianceEvaluationResult => {\n const result = baseEvaluate.call(base, request), o = (request.target as { outgoingDirectionUnitVector: { x: number; y: number; z: number } }).outgoingDirectionUnitVector;\n const t = distance / -o.z;\n return { ...result, spectralRadianceWattsPerSquareMeterSteradianNanometer: blurredAt(-o.x * t / scale, -o.y * t / scale, request.wavelengthNanometers) };\n };\n // 2.6: the result is the base result with only its radiance replaced (same keys and records), so an engine-built base\n // evaluator keeps its mark (see core/internal-radiance-evaluator.ts).\n if (isInternalSceneRadianceEvaluator(baseEvaluate)) {\n markInternalSceneRadianceEvaluator(evaluateRadiance);\n // #394: its radiance is the convolved value at one lattice site (shift s, lattice column li, row lj) per wavelength, so\n // the lean executor may read it by that key: the same plane point, lattice choice and band value as evaluateRadiance.\n registerInternalRadianceAccess(evaluateRadiance, {\n tabulated: false,\n keyOfDirection(o): number | undefined {\n if (!(-o.z > 0)) return undefined;\n const t = distance / -o.z, u = -o.x * t / scale, v = -o.y * t / scale, fi = u / g - 0.5 + W / 2, fj = -v / g - 0.5 + H / 2;\n for (let s = 0; s < shifts.length; s++) {\n const shift = shifts[s]!, i = Math.round(fi - shift.x), j = Math.round(fj - shift.y);\n if (Math.abs(fi - shift.x - i) > LATTICE_TOLERANCE_SITES || Math.abs(fj - shift.y - j) > LATTICE_TOLERANCE_SITES) continue;\n const li = i + M, lj = j + M;\n if (li < lx0 || lj < ly0 || li >= lx1 || lj >= ly1) return undefined;\n return (s * LH + lj) * LW + li;\n }\n return undefined;\n },\n radianceOfKey(key, nm): number {\n const w = index.get(nm);\n if (w === undefined) throw new InvalidConfigurationError(\"Diffraction query is off the site lattice; the object-space convolution does not apply.\");\n const li = key % LW, rest = (key - li) / LW, lj = rest % LH, s = (rest - lj) / LH;\n return band(Math.floor((lj - ly0) / BAND_ROWS))[s]![w]![((lj - ly0) % BAND_ROWS) * NW + li - lx0]!;\n }\n });\n }\n return {\n sceneId: base.sceneId, providerProfileId: base.providerProfileId, radianceAt: base.radianceAt,\n evaluateRadiance,\n evaluateApertureRadiance(): SceneRadianceEvaluationResult {\n throw new InvalidConfigurationError(\"Diffraction by object-space convolution does not take pupil rays.\");\n }\n };\n}\n\n/** Largest kernel sum, and largest sample, the object-space convolution accepts (as `IRRADIANCE_CONVOLUTION_LIMITS`). */\nconst MAXIMUM_KERNEL_SUM = 1 + 2 ** -20, MAXIMUM_SAMPLE = 2 ** 100;\n\n/** #492: a site kernel of radius R, checked as `calculateIrradianceConvolution` checks its kernels. */\nfunction checkedSiteKernel(kernel: Float64Array, R: number): Float64Array {\n if (!(kernel instanceof Float64Array) || kernel.length !== (2 * R + 1) ** 2) throw new InvalidConfigurationError(\"Site kernels must be (2R + 1)² taps.\");\n let sum = 0;\n for (let k = 0; k < kernel.length; k++) {\n const w = kernel[k]!;\n if (!(w >= 0 && w <= 1)) throw new InvalidConfigurationError(\"Site kernel weights must be finite numbers in [0, 1].\");\n sum += w;\n }\n if (sum > MAXIMUM_KERNEL_SUM) throw new InvalidConfigurationError(\"A PSF kernel may not create energy (sum exceeds 1).\");\n return kernel;\n}\n\n/** #492: the non-zero taps of a kernel as offsets into a grid of `gridWidth` columns (−v·gridWidth − u) and weights, v outer, u inner, ascending. */\nfunction kernelTaps(kernel: Float64Array, R: number, gridWidth: number): { offsets: Int32Array; weights: Float64Array } {\n const offsets: number[] = [], weights: number[] = [];\n for (let v = -R, t = 0; v <= R; v++) for (let u = -R; u <= R; u++, t++) {\n const w = kernel[t]!;\n if (w !== 0) { offsets.push(-v * gridWidth - u); weights.push(w); }\n }\n return { offsets: Int32Array.from(offsets), weights: Float64Array.from(weights) };\n}\n\n/**\n * #492: out(x, y) = Σ_t K(t)·samples(x + R − t_u, y + R − t_v) for the band's own values only (x < width, y < rows): every tap of\n * these lies inside the grid (it holds R extra samples on each side), so no boundary rule applies. Samples are checked as\n * `calculateIrradianceConvolution` checks them.\n */\nfunction gatherInterior(samples: Float64Array, taps: { offsets: Int32Array; weights: Float64Array }, gridWidth: number, width: number, rows: number, R: number): Float64Array {\n for (let k = 0; k < samples.length; k++) {\n const v = samples[k]!;\n if (!(v >= 0 && v <= MAXIMUM_SAMPLE)) throw new InvalidConfigurationError(\"Irradiance samples must be finite, non-negative and within the declared magnitude.\");\n }\n const { offsets, weights } = taps, count = weights.length, out = new Float64Array(width * rows);\n for (let y = 0; y < rows; y++) {\n const rowBase = (y + R) * gridWidth + R;\n for (let x = 0; x < width; x++) {\n const base = rowBase + x;\n let sum = 0;\n for (let k = 0; k < count; k++) sum += samples[base + offsets[k]!]! * weights[k]!;\n out[y * width + x] = sum;\n }\n }\n return out;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"diffraction-provider.js","sourceRoot":"","sources":["../../src/facade/diffraction-provider.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Fast execution of `simulateCapture`'s `lens.diffraction` (2.1): an object-space convolution in the scene\n * provider, instead of one scene query per PSF tap in the environment PSF quadrature.\n *\n * The environment quadrature computes, at each site centre q and spectral node λ,\n * E(q, λ) = Σ_k K_λ(k)·T·L(s_k(q), λ),\n * where s_k(q) is the tap's source point (`sensorPsfSourcePoint`), L the scene radiance at the plane point\n * that source point sees, and T the radiance-to-irradiance factor. For the facade's planar scene seen\n * through the ideal rectilinear projection with a still camera and no lens field mapping, field throughput or\n * pupil rays:\n * - T is the same at every sensor point (paraxial π/(4·N_w²), no cos⁴ term), and\n * - with the kernel sampled on the site pitch, every source point is the centre of another site, so the plane\n * points form one regular lattice: u = (i + ½ − W/2)·2/w, v = −(j + ½ − H/2)·2/w (frame units, native\n * site (i, j), W×H native sites, w output width).\n * So E(q, λ) = T·B(q, λ) with B = K_λ ⊛ L sampled on that lattice: the same sum, in a different floating-point\n * order. B is computed once per spectral node with the engine's isoplanatic convolution\n * (`calculateIrradianceConvolution`, kernels from `resolveLensPsfConvolutionKernels`, exact site sampling) over a\n * grid that holds every source (the native raster plus the kernel radius on each side), in row bands; each band gathers only\n * its own values, the grid's interior (#419, `createIrradianceConvolutionInteriorRunner`: each value bit-identical to\n * `calculateIrradianceConvolution`'s there, without the 2R rows and columns of the band's grid that no query reads). The\n * provider then answers each site-centre query with B instead of L, and the environment request declares no\n * PSF. Incoherent imaging is a linear superposition of intensity PSFs, so convolving radiance on the object\n * plane and convolving irradiance on the image plane agree for a planar object and a space-invariant PSF\n * (MIT OpenCourseWare 2.71, lecture 22, free; also see: Goodman, Introduction to Fourier Optics, 4th ed., §7.1).\n *\n * With an anti-aliasing point-splitting filter (2.1, `sensor.antiAliasing`) the environment queries the PSF taps\n * around each pre-filter source point q − a (a = a split offset) instead of around q. Those taps lie on the site\n * lattice shifted by a, so the same argument holds on each shifted lattice: B is computed once per distinct\n * fractional shift (offsets that differ by whole sites share one lattice; the centred four-spot filter with a\n * one-site separation needs a single half-site-shifted lattice) over the native raster widened by the largest\n * offset, and the environment's spatial quadrature still forms the weighted split sum.\n *\n * Region renders (2.6, `window`): only the lattice rows and columns that the region's sites can query (the window\n * plus the largest offset on each side) are convolved, over a grid that adds the kernel radius on each side. Every\n * output value is the same gather as in the whole render: the grid always holds every tap of every value it keeps\n * (real scene radiance out to the kernel radius, never a truncated edge), the single kernel patch does not depend on\n * the grid's origin, and the gather (`convolveIrradianceRows`, and its interior form) sums each value in a fixed tap order (v outer, u inner). Narrowing\n * the grid therefore removes only values that no query reads, and the kept values are bit-identical.\n *\n * A query that does not land on one of the lattices (within 1e-6 site) is refused rather than approximated: the\n * facade uses this path only when the lattice argument above holds. A query outside the window is refused too.\n *\n * Defocus (#492, `lens.defocus`): the same argument holds for any space-invariant kernel on the site lattice, so the facade\n * passes `siteKernels` instead (the geometric defocus disc, or each node's diffraction kernel convolved with it). Their radius\n * may exceed the public 32-site convolution limit, so this path does not call `calculateIrradianceConvolution`: it checks the\n * samples and the kernel sums as that function does and gathers only the band's own values (`gatherInterior`), each summed\n * over the taps in the same fixed order (v outer, u inner, ascending; zero taps skipped, which adds exact zeros only). Like\n * the diffraction path (#419), it does not compute the 2R grid rows and columns around a band.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { isInternalSceneRadianceEvaluator, markInternalSceneRadianceEvaluator, registerInternalRadianceAccess } from \"../core/internal-radiance-evaluator.js\";\nimport type { SceneRadianceEvaluationRequest, SceneRadianceEvaluationResult } from \"../schema/scene-radiance.js\";\nimport { createIrradianceConvolutionInteriorRunner } from \"../optics/irradiance-convolution.js\";\nimport { siteDiffractionKernel } from \"../optics/site-diffraction-kernel.js\";\nimport type { ResolveLensSampledPsfInput } from \"../optics/lens-psf-profile.js\";\nimport type { PlanarSceneRadianceProvider } from \"./scene-radiance.js\";\n\n/** Rows of native sites per convolution band, and the bands kept. Banding changes memory only, never values. */\nconst BAND_ROWS = 32;\nconst CACHED_BANDS = 4;\nconst LATTICE_TOLERANCE_SITES = 1e-6;\n\nexport interface DiffractedPlanarProviderInput {\n base: PlanarSceneRadianceProvider;\n /** The optical state of the sampled PSF, as for `resolveLensSampledPsf`, without field point and wavelength. Unused with `siteKernels`. */\n psf?: Omit<ResolveLensSampledPsfInput, \"fieldPointMm\" | \"wavelengthNm\">;\n /**\n * #492: the kernel of each spectral node on the site lattice, (2·kernelRadius + 1)² taps in row-major order, applied\n * instead of the diffraction kernels of `psf` (the defocus disc, or each node's diffraction kernel convolved with it).\n * Any radius; each kernel's sum may not exceed 1 + 2^-20.\n */\n siteKernels?: (wavelengthNm: number) => Float64Array;\n /** Spectral nodes the environment queries (the profile's wavelength nodes). */\n wavelengthsNm: readonly number[];\n kernelRadius: number;\n nativeWidth: number;\n nativeHeight: number;\n /** Output (active) width in sites: frame units are 2/outputWidth per site. */\n outputWidth: number;\n sitePitchMicrometers: number;\n /** Planar geometry of the base provider, to map query directions to plane points exactly as it does. */\n distanceM: number;\n metresPerFrameUnit: number;\n /**\n * Offsets of the query points from the site centres, in sites (+x right, +y down): the anti-aliasing split\n * offsets with their sign reversed (the environment queries q − a). Default: one zero offset.\n */\n queryOffsetsSites?: readonly { x: number; y: number }[];\n /**\n * Region renders (2.6): the native sites that will be queried (x, y, width, height in the native raster). Only the\n * lattice they can reach is convolved; values are bit-identical to the whole render's. Default: the whole raster.\n */\n window?: { x: number; y: number; width: number; height: number };\n /** Called with the duration in ms of each band convolution (diagnostics only; never changes values). */\n onConvolution?: (milliseconds: number) => void;\n}\n\n/** Internal (not exported from the package): the base provider with diffraction applied as an object-space convolution. */\nexport function createDiffractedPlanarProvider(input: DiffractedPlanarProviderInput): PlanarSceneRadianceProvider {\n const { base, wavelengthsNm, nativeWidth: W, nativeHeight: H, kernelRadius: R } = input;\n const g = 2 / input.outputWidth, pitch = input.sitePitchMicrometers;\n const index = new Map(wavelengthsNm.map((nm, i) => [nm, i]));\n // One lattice per distinct fractional query offset; M extra sites per side hold the offset queries.\n const offsets = input.queryOffsetsSites ?? [{ x: 0, y: 0 }];\n const fraction = (value: number): number => { const f = value - Math.floor(value); return f > 1 - LATTICE_TOLERANCE_SITES ? 0 : f < LATTICE_TOLERANCE_SITES ? 0 : f; };\n const shifts: { x: number; y: number }[] = [];\n for (const o of offsets) {\n const f = { x: fraction(o.x), y: fraction(o.y) };\n if (!shifts.some((s) => Math.abs(s.x - f.x) <= LATTICE_TOLERANCE_SITES && Math.abs(s.y - f.y) <= LATTICE_TOLERANCE_SITES)) shifts.push(f);\n }\n const M = Math.max(0, ...offsets.map((o) => Math.ceil(Math.max(Math.abs(o.x), Math.abs(o.y)) - LATTICE_TOLERANCE_SITES)));\n const LW = W + 2 * M, LH = H + 2 * M;\n // Lattice window (indices i + M, j + M): the sites the region queries plus the largest offset on each side, clipped\n // to the lattice. A site i queries i + floor(offset), and floor(offset) lies in [-M, M].\n const win = input.window ?? { x: 0, y: 0, width: W, height: H };\n const lx0 = Math.max(0, win.x), lx1 = Math.min(LW, win.x + win.width + 2 * M);\n const ly0 = Math.max(0, win.y), ly1 = Math.min(LH, win.y + win.height + 2 * M);\n if (!(lx0 < lx1 && ly0 < ly1)) throw new InvalidConfigurationError(\"Diffraction window must overlap the native raster.\");\n const NW = lx1 - lx0;\n // One kernel per wavelength, on the site grid, from the engine's own tap-to-site mapping (field point 0, 0); kept across calls.\n const siteKernels = input.siteKernels;\n if (!siteKernels && !input.psf) throw new InvalidConfigurationError(\"The object-space convolution needs a PSF or site kernels.\");\n const kernels = wavelengthsNm.map((wavelengthNm) => siteKernels ? checkedSiteKernel(siteKernels(wavelengthNm), R) :\n siteDiffractionKernel(input.psf!, wavelengthNm, pitch, R, \"Diffraction kernels must sample the site pitch exactly.\"));\n // #492: each site kernel's non-zero taps as grid offsets, in the gather's order.\n const taps = siteKernels ? kernels.map((kernel) => kernelTaps(kernel, R, NW + 2 * R)) : [];\n const gridWidth = NW + 2 * R;\n const now = (): number => globalThis.performance?.now() ?? Date.now();\n const bands = new Map<number, Float64Array[][]>();\n const materialAt = base.chartMaterialAt?.bind(base), materialRadiance = base.materialRadiance?.bind(base);\n function band(b: number): Float64Array[][] {\n const cached = bands.get(b);\n if (cached) { bands.delete(b); bands.set(b, cached); return cached; }\n const started = input.onConvolution ? now() : 0;\n const y0 = ly0 + b * BAND_ROWS, rows = Math.min(BAND_ROWS, ly1 - y0), gridHeight = rows + 2 * R, size = gridWidth * gridHeight;\n // #453: the band's shifts × spectral nodes convolutions share one geometry, validated once (the first with every check of\n // calculateIrradianceConvolution; every later one still checks its samples and kernel). #419: only the band's own rows × NW\n // values are gathered (the grid's interior), each bit-identical to calculateIrradianceConvolution's value there.\n const convolve = siteKernels ? undefined : createIrradianceConvolutionInteriorRunner({ schemaVersion: \"0.1.0\", width: gridWidth, height: gridHeight, kernelRadius: R,\n patchWidth: gridWidth, patchHeight: gridHeight, boundary: \"zero-outside-grid\" });\n const values = shifts.map((shift) => {\n // The plane point of lattice grid sample (gx, gy) of this shift, the same expressions for both fills below.\n const vOf = (gy: number): number => shift.y === 0 ? -(y0 + gy - R - M + 0.5 - H / 2) * g : -(y0 + gy - R - M + 0.5 + shift.y - H / 2) * g;\n const uOf = (x: number): number => shift.x === 0 ? (x - R - M + 0.5 - W / 2) * g : (x - R - M + 0.5 + shift.x - W / 2) * g;\n // #453, material scenes (chart presets and caller material scenes): radianceAt(u, v, nm) is materialRadiance(chartMaterialAt(u, v), nm)\n // (scene-radiance.ts), so the material is looked up once per lattice point and each node's samples come from one\n // materialRadiance per material present, the same numbers as one radianceAt per point and node.\n let materialOf: Int32Array | undefined;\n if (materialAt && materialRadiance) {\n materialOf = new Int32Array(size);\n for (let gy = 0; gy < gridHeight; gy++) {\n const v = vOf(gy);\n for (let gx = 0, x = lx0; gx < gridWidth; gx++, x++) materialOf[gy * gridWidth + gx] = materialAt(uOf(x), v);\n }\n }\n return wavelengthsNm.map((nm, w) => {\n const samples = new Float64Array(size);\n if (materialOf) {\n const radiance = new Map<number, number>();\n for (let i = 0; i < size; i++) {\n const m = materialOf[i]!;\n let value = radiance.get(m);\n if (value === undefined) { value = materialRadiance!(m, nm); radiance.set(m, value); }\n samples[i] = value;\n }\n } else {\n for (let gy = 0; gy < gridHeight; gy++) {\n const v = vOf(gy);\n for (let gx = 0, x = lx0; gx < gridWidth; gx++, x++) samples[gy * gridWidth + gx] = base.radianceAt(uOf(x), v, nm);\n }\n }\n if (!convolve) return gatherInterior(samples, taps[w]!, gridWidth, NW, rows, R);\n return convolve(samples, kernels[w]!);\n });\n });\n bands.set(b, values);\n if (bands.size > CACHED_BANDS) bands.delete(bands.keys().next().value!);\n if (input.onConvolution) input.onConvolution(now() - started);\n return values;\n }\n function blurredAt(u: number, v: number, nm: number): number {\n const w = index.get(nm), fi = u / g - 0.5 + W / 2, fj = -v / g - 0.5 + H / 2;\n if (w !== undefined) for (let s = 0; s < shifts.length; s++) {\n const shift = shifts[s]!, i = Math.round(fi - shift.x), j = Math.round(fj - shift.y);\n if (Math.abs(fi - shift.x - i) > LATTICE_TOLERANCE_SITES || Math.abs(fj - shift.y - j) > LATTICE_TOLERANCE_SITES) continue;\n const li = i + M, lj = j + M;\n if (li < lx0 || lj < ly0 || li >= lx1 || lj >= ly1) break;\n return band(Math.floor((lj - ly0) / BAND_ROWS))[s]![w]![((lj - ly0) % BAND_ROWS) * NW + li - lx0]!;\n }\n throw new InvalidConfigurationError(\"Diffraction query is off the site lattice; the object-space convolution does not apply.\");\n }\n const scale = input.metresPerFrameUnit, distance = input.distanceM, baseEvaluate = base.evaluateRadiance;\n const evaluateRadiance = (request: Readonly<SceneRadianceEvaluationRequest>): SceneRadianceEvaluationResult => {\n const result = baseEvaluate.call(base, request), o = (request.target as { outgoingDirectionUnitVector: { x: number; y: number; z: number } }).outgoingDirectionUnitVector;\n const t = distance / -o.z;\n return { ...result, spectralRadianceWattsPerSquareMeterSteradianNanometer: blurredAt(-o.x * t / scale, -o.y * t / scale, request.wavelengthNanometers) };\n };\n // 2.6: the result is the base result with only its radiance replaced (same keys and records), so an engine-built base\n // evaluator keeps its mark (see core/internal-radiance-evaluator.ts).\n if (isInternalSceneRadianceEvaluator(baseEvaluate)) {\n markInternalSceneRadianceEvaluator(evaluateRadiance);\n // #394: its radiance is the convolved value at one lattice site (shift s, lattice column li, row lj) per wavelength, so\n // the lean executor may read it by that key: the same plane point, lattice choice and band value as evaluateRadiance.\n registerInternalRadianceAccess(evaluateRadiance, {\n tabulated: false,\n keyOfDirection(o): number | undefined {\n if (!(-o.z > 0)) return undefined;\n const t = distance / -o.z, u = -o.x * t / scale, v = -o.y * t / scale, fi = u / g - 0.5 + W / 2, fj = -v / g - 0.5 + H / 2;\n for (let s = 0; s < shifts.length; s++) {\n const shift = shifts[s]!, i = Math.round(fi - shift.x), j = Math.round(fj - shift.y);\n if (Math.abs(fi - shift.x - i) > LATTICE_TOLERANCE_SITES || Math.abs(fj - shift.y - j) > LATTICE_TOLERANCE_SITES) continue;\n const li = i + M, lj = j + M;\n if (li < lx0 || lj < ly0 || li >= lx1 || lj >= ly1) return undefined;\n return (s * LH + lj) * LW + li;\n }\n return undefined;\n },\n radianceOfKey(key, nm): number {\n const w = index.get(nm);\n if (w === undefined) throw new InvalidConfigurationError(\"Diffraction query is off the site lattice; the object-space convolution does not apply.\");\n const li = key % LW, rest = (key - li) / LW, lj = rest % LH, s = (rest - lj) / LH;\n return band(Math.floor((lj - ly0) / BAND_ROWS))[s]![w]![((lj - ly0) % BAND_ROWS) * NW + li - lx0]!;\n }\n });\n }\n return {\n sceneId: base.sceneId, providerProfileId: base.providerProfileId, radianceAt: base.radianceAt,\n evaluateRadiance,\n evaluateApertureRadiance(): SceneRadianceEvaluationResult {\n throw new InvalidConfigurationError(\"Diffraction by object-space convolution does not take pupil rays.\");\n }\n };\n}\n\n/** Largest kernel sum, and largest sample, the object-space convolution accepts (as `IRRADIANCE_CONVOLUTION_LIMITS`). */\nconst MAXIMUM_KERNEL_SUM = 1 + 2 ** -20, MAXIMUM_SAMPLE = 2 ** 100;\n\n/** #492: a site kernel of radius R, checked as `calculateIrradianceConvolution` checks its kernels. */\nfunction checkedSiteKernel(kernel: Float64Array, R: number): Float64Array {\n if (!(kernel instanceof Float64Array) || kernel.length !== (2 * R + 1) ** 2) throw new InvalidConfigurationError(\"Site kernels must be (2R + 1)² taps.\");\n let sum = 0;\n for (let k = 0; k < kernel.length; k++) {\n const w = kernel[k]!;\n if (!(w >= 0 && w <= 1)) throw new InvalidConfigurationError(\"Site kernel weights must be finite numbers in [0, 1].\");\n sum += w;\n }\n if (sum > MAXIMUM_KERNEL_SUM) throw new InvalidConfigurationError(\"A PSF kernel may not create energy (sum exceeds 1).\");\n return kernel;\n}\n\n/** #492: the non-zero taps of a kernel as offsets into a grid of `gridWidth` columns (−v·gridWidth − u) and weights, v outer, u inner, ascending. */\nfunction kernelTaps(kernel: Float64Array, R: number, gridWidth: number): { offsets: Int32Array; weights: Float64Array } {\n const offsets: number[] = [], weights: number[] = [];\n for (let v = -R, t = 0; v <= R; v++) for (let u = -R; u <= R; u++, t++) {\n const w = kernel[t]!;\n if (w !== 0) { offsets.push(-v * gridWidth - u); weights.push(w); }\n }\n return { offsets: Int32Array.from(offsets), weights: Float64Array.from(weights) };\n}\n\n/**\n * #492: out(x, y) = Σ_t K(t)·samples(x + R − t_u, y + R − t_v) for the band's own values only (x < width, y < rows): every tap of\n * these lies inside the grid (it holds R extra samples on each side), so no boundary rule applies. Samples are checked as\n * `calculateIrradianceConvolution` checks them.\n */\nfunction gatherInterior(samples: Float64Array, taps: { offsets: Int32Array; weights: Float64Array }, gridWidth: number, width: number, rows: number, R: number): Float64Array {\n for (let k = 0; k < samples.length; k++) {\n const v = samples[k]!;\n if (!(v >= 0 && v <= MAXIMUM_SAMPLE)) throw new InvalidConfigurationError(\"Irradiance samples must be finite, non-negative and within the declared magnitude.\");\n }\n const { offsets, weights } = taps, count = weights.length, out = new Float64Array(width * rows);\n for (let y = 0; y < rows; y++) {\n const rowBase = (y + R) * gridWidth + R;\n for (let x = 0; x < width; x++) {\n const base = rowBase + x;\n let sum = 0;\n for (let k = 0; k < count; k++) sum += samples[base + offsets[k]!]! * weights[k]!;\n out[y * width + x] = sum;\n }\n }\n return out;\n}\n"]}
|
|
@@ -33,7 +33,7 @@ export function parsePrepareDisplayViewOptions(value) {
|
|
|
33
33
|
throw new InvalidConfigurationError("prepareDisplayView options.gpuDevice needs gpu \"auto\" or \"require\".");
|
|
34
34
|
return { gpu: mode, gpuDevice };
|
|
35
35
|
}
|
|
36
|
-
const CPU_LIMITATIONS = Object.freeze(["Float64 engine reference execution; results are the reference by definition"]);
|
|
36
|
+
const CPU_LIMITATIONS = /* @__PURE__ */ Object.freeze(["Float64 engine reference execution; results are the reference by definition"]);
|
|
37
37
|
/** Internal: the execution record of a display view rendered on the CPU reference. `requested` names what `gpu` asked for. */
|
|
38
38
|
export function cpuDisplayViewExecution(gpu, fallbackReason, adapter, conformance, detail, compositeProbe = null) {
|
|
39
39
|
const requestedBackend = gpu === "off" ? "cpu-reference" : "webgpu-f32";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"display-view-gpu.js","sourceRoot":"","sources":["../../src/facade/display-view-gpu.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AA6B3E,uEAAuE;AACvE,MAAM,UAAU,8BAA8B,CAAC,KAAc;IAC3D,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;IACrE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,yBAAyB,CAAC,kEAAkE,CAAC,CAAC;IACjL,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,WAAW;YAAE,MAAM,IAAI,yBAAyB,CAAC,4CAA4C,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;IAC9K,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,KAAgC,CAAC;IAC5D,MAAM,IAAI,GAAuB,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAyB,CAAC;IACvF,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,SAAS;QAAE,MAAM,IAAI,yBAAyB,CAAC,0EAA0E,CAAC,CAAC;IAC7K,IAAI,SAAS,KAAK,SAAS,IAAI,CAAC,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,IAAI,CAAC;QAAE,MAAM,IAAI,yBAAyB,CAAC,iHAAiH,CAAC,CAAC;IAC7O,IAAI,SAAS,KAAK,SAAS,IAAI,IAAI,KAAK,KAAK;QAAE,MAAM,IAAI,yBAAyB,CAAC,yEAAyE,CAAC,CAAC;IAC9J,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AAClC,CAAC;AAgDD,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,6EAA6E,CAAC,CAAC,CAAC;AAEvH,8HAA8H;AAC9H,MAAM,UAAU,uBAAuB,CAAC,GAAuB,EAAE,cAAmD,EAAE,OAA6C,EACjK,WAA6C,EAAE,MAAe,EAAE,iBAAmD,IAAI;IACvH,MAAM,gBAAgB,GAAuB,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,YAAY,CAAC;IAC5F,MAAM,WAAW,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,eAAe,EAAE,+BAA+B,GAAG,GAAG,GAAG,iCAAiC,GAAG,MAAM,CAAC,CAAC,CAAC;IACrL,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,kBAAkB,EAAE,IAAI,EAAE,KAAK;QACvJ,uBAAuB,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,gCAAgC,EAAE,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC,CAAC;AACvK,CAAC;AAkED,IAAI,eAAe,GAAyC,IAAI,CAAC;AACjE;;;;GAIG;AACH,MAAM,UAAU,gCAAgC,CAAC,OAA6C;IAC5F,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,OAAO,KAAK,UAAU;QAAE,MAAM,IAAI,yBAAyB,CAAC,8DAA8D,CAAC,CAAC;IAC3J,MAAM,QAAQ,GAAG,eAAe,CAAC;IACjC,eAAe,GAAG,OAAO,CAAC;IAC1B,OAAO,QAAQ,CAAC;AAClB,CAAC;AACD,wCAAwC;AACxC,MAAM,UAAU,6BAA6B,KAA2C,OAAO,eAAe,CAAC,CAAC,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * #481: how a prepared display view chooses between a WebGPU preview renderer and the CPU reference, and how a render labels\n * which ran. This module holds the option, the label and the renderer contract and imports nothing from the GPU code, so a\n * bundle that never asks for the GPU (`gpu: \"off\"`, the default) does not contain it; the device handling lives in\n * `display-view-gpu-session.ts`, loaded on demand by `prepareDisplayView` when `gpu` is `\"auto\"` or `\"require\"`.\n *\n * The vocabulary is the image-kernel accelerator's (`createImageKernelAccelerator`, docs/WEBGPU.md): `\"auto\"` is\n * `backend: \"webgpu-f32\"` with `fallback: \"cpu-reference\"`, `\"require\"` is `fallback: \"fail\"`, `\"off\"` is\n * `backend: \"cpu-reference\"`. The render's `diagnostics.fast.execution` names the backend that ran, the fallback reason and the\n * bound in the fields of `ImageKernelExecution`, plus the adapter and the run-time conformance check.\n *\n * No GPU display-view renderer exists yet (#478, #479): until one registers itself through {@link setDisplayViewGpuRendererFactory},\n * `\"auto\"` runs the CPU reference labelled `unsupported-on-backend` without touching a device, and `\"require\"` fails with that reason.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport type { ChartCompositeProbeRecord, ImageKernelAdapterDescription, ImageKernelBackend, ImageKernelExecution, ImageKernelFallbackReason } from \"../gpu/image-kernel-execution.js\";\nimport type { DisplayViewRenderResult, DisplayViewSetup } from \"./display-view.js\";\nimport type { SimulateCaptureFastReport } from \"./simulate-capture.js\";\n\n/**\n * 2.11 (#481): whether a prepared display view may render on the GPU. `\"off\"` (the default) is the CPU reference, today's\n * behaviour byte for byte. `\"auto\"` renders on WebGPU when a conforming device is available and the request is supported, and\n * otherwise runs the CPU reference and says why. `\"require\"` fails instead of falling back. In the accelerator's words: `\"auto\"`\n * is `backend: \"webgpu-f32\"` with `fallback: \"cpu-reference\"`, `\"require\"` is `fallback: \"fail\"`, `\"off\"` is `backend: \"cpu-reference\"`.\n */\nexport type DisplayViewGpuMode = \"off\" | \"auto\" | \"require\";\n\n/** 2.11 (#481): the second argument of `prepareDisplayView`. */\nexport interface PrepareDisplayViewOptions {\n /** See {@link DisplayViewGpuMode}. Default `\"off\"`. */\n gpu?: DisplayViewGpuMode;\n /**\n * Where the device comes from, with `gpu: \"auto\"` or `\"require\"`: a WebGPU entry point (a worker's `navigator.gpu`), or an\n * `ImageKernelAccelerator` whose device the view shares (the accelerator keeps ownership; `dispose()` of the prepared view\n * leaves it alone). Without it the engine acquires a device from `globalThis.navigator.gpu` and owns it until `dispose()`.\n * Refused with `gpu: \"off\"`.\n */\n gpuDevice?: unknown;\n}\n\n/** The parsed form of {@link PrepareDisplayViewOptions}. @internal */\nexport interface ParsedPrepareDisplayViewOptions { gpu: DisplayViewGpuMode; gpuDevice: unknown }\n\n/** Internal: validates the second argument of `prepareDisplayView`. */\nexport function parsePrepareDisplayViewOptions(value: unknown): ParsedPrepareDisplayViewOptions {\n if (value === undefined) return { gpu: \"off\", gpuDevice: undefined };\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) throw new InvalidConfigurationError(\"prepareDisplayView options must be an object { gpu, gpuDevice }.\");\n for (const key of Object.keys(value)) if (key !== \"gpu\" && key !== \"gpuDevice\") throw new InvalidConfigurationError(\"Unknown prepareDisplayView options field: \" + key + \".\");\n const { gpu, gpuDevice } = value as Record<string, unknown>;\n const mode: DisplayViewGpuMode = gpu === undefined ? \"off\" : gpu as DisplayViewGpuMode;\n if (mode !== \"off\" && mode !== \"auto\" && mode !== \"require\") throw new InvalidConfigurationError(\"prepareDisplayView options.gpu must be \\\"off\\\", \\\"auto\\\" or \\\"require\\\".\");\n if (gpuDevice !== undefined && (typeof gpuDevice !== \"object\" || gpuDevice === null)) throw new InvalidConfigurationError(\"prepareDisplayView options.gpuDevice must be a WebGPU entry point (navigator.gpu) or an ImageKernelAccelerator.\");\n if (gpuDevice !== undefined && mode === \"off\") throw new InvalidConfigurationError(\"prepareDisplayView options.gpuDevice needs gpu \\\"auto\\\" or \\\"require\\\".\");\n return { gpu: mode, gpuDevice };\n}\n\n/**\n * 2.11 (#481): why a display view that asked for the GPU (`gpu: \"auto\"`) ran the CPU reference. The accelerator's acquisition\n * reasons, plus: `unsupported-on-backend` (no GPU display-view renderer exists in this version, or it does not support the\n * request), `conformance-failed` (the device failed the run-time self-check before the view's first GPU render), `device-lost`\n * (the device was lost; the rest of the view runs on the CPU) and `disposed` (the prepared view was disposed).\n */\nexport type DisplayViewGpuFallbackReason = ImageKernelFallbackReason | \"unsupported-on-backend\" | \"conformance-failed\" | \"device-lost\" | \"disposed\";\n\n/** 2.11 (#481): the run-time conformance self-check of a device, run once before the view's first GPU render. */\nexport interface DisplayViewGpuConformance {\n /** The ids of the cases run, in order (the built-in image-kernel cases, then the renderer's own). */\n cases: readonly string[];\n passed: boolean;\n /** The first case that failed, or null. */\n failedCase: string | null;\n /** What the failed case reported, or null. */\n detail: string | null;\n}\n\n/**\n * 2.11 (#481): where a display view's render ran, in the words of the image-kernel execution record (`ImageKernelExecution`):\n * `backend` names the path that ran (`cpu-reference`, the float64 engine reference, or `webgpu-f32`, a float32 approximation\n * within `errorBound`), `requestedBackend` what `gpu` asked for, and `fallbackReason` why a request for the GPU ran the CPU.\n * `adapter` describes the device's adapter whenever one was involved, also when the view then fell back; `conformance` is\n * the device's self-check once it has run. A CPU render keeps `assurance: \"engine-reference\"` and `fast: false`.\n */\nexport interface DisplayViewExecution extends Omit<ImageKernelExecution, \"fallbackReason\"> {\n /** The `gpu` option the view was prepared with. */\n gpu: DisplayViewGpuMode;\n fallbackReason: DisplayViewGpuFallbackReason | null;\n adapter: ImageKernelAdapterDescription | null;\n conformance: DisplayViewGpuConformance | null;\n /**\n * 2.11: the composite chart kernel's device probe when this render needed it (composite charts, the 2.3 elements and\n * `material-layers` scenes): the device class and the product path the kernel ran with, or, on a refusal (`fallbackReason`\n * `unsupported-on-backend`), why. Null when the render did not run the probe (the 2.0 presets, `gpu: \"off\"`).\n */\n compositeProbe: ChartCompositeProbeRecord | null;\n}\n\n/** 2.11 (#481): `diagnostics.fast` of a display view: the capture's report plus where the render ran. */\nexport interface DisplayViewFastReport extends SimulateCaptureFastReport {\n /** Where this render ran (see {@link DisplayViewExecution}). `assurance` above follows it. */\n execution: DisplayViewExecution;\n}\n\nconst CPU_LIMITATIONS = Object.freeze([\"Float64 engine reference execution; results are the reference by definition\"]);\n\n/** Internal: the execution record of a display view rendered on the CPU reference. `requested` names what `gpu` asked for. */\nexport function cpuDisplayViewExecution(gpu: DisplayViewGpuMode, fallbackReason: DisplayViewGpuFallbackReason | null, adapter: ImageKernelAdapterDescription | null,\n conformance: DisplayViewGpuConformance | null, detail?: string, compositeProbe: ChartCompositeProbeRecord | null = null): DisplayViewExecution {\n const requestedBackend: ImageKernelBackend = gpu === \"off\" ? \"cpu-reference\" : \"webgpu-f32\";\n const limitations = detail === undefined ? CPU_LIMITATIONS : Object.freeze([...CPU_LIMITATIONS, \"WebGPU was requested (gpu: \\\"\" + gpu + \"\\\") and the CPU reference ran: \" + detail]);\n return Object.freeze({ gpu, backend: \"cpu-reference\", requestedBackend, fallbackReason, arithmetic: \"float64\", assurance: \"engine-reference\", fast: false,\n bitIdenticalToReference: true, errorBound: null, diagnosticsExact: true, diagnosticUncertaintySampleCount: 0, limitations, adapter, conformance, compositeProbe });\n}\n\n// ---------------------------------------------------------------------------------------------------------------\n// The renderer contract (#478 implements it; until then the only implementation is a test fake).\n\n/**\n * Internal (#481): the device a renderer or conformance case runs on. It is the engine's `WebGpuRuntime` object\n * (`src/gpu/webgpu-runtime.ts`: `device`, `guard`, `destroy` and the rest), seen here through its WebGPU-free members only so\n * that no WebGPU type reaches the published declarations (docs/WEBGPU.md); a renderer in the engine casts it to `WebGpuRuntime`.\n */\nexport interface DisplayViewGpuRuntimeHandle {\n readonly adapter: ImageKernelAdapterDescription | null;\n readonly maximumStorageBindingBytes: number;\n readonly maximumWorkgroupsPerDimension: number;\n isLost(): boolean;\n}\n\n/** What a prepared request asks of a GPU renderer (`supports`): the options that shape a render. */\nexport interface DisplayViewGpuRequest {\n ahd: boolean;\n diffraction: boolean;\n antiAliasing: boolean;\n /** Pixel-aperture samples per axis (1: centre sampling). */\n boxSamples: number;\n toneCurve: \"identity\" | \"positive-reinhard-per-channel\";\n /**\n * #492: true when `lens.defocus` needs the defocus disc (out of focus): the expected signal then carries the disc, or each\n * node's diffraction kernel convolved with it, as site kernels (#492 step 2b), which the engine's renderer gathers in its\n * Quality site pass (step 2c). Absent or false otherwise.\n */\n defocus?: boolean;\n /** The scene's form: an engine chart, a declared `material-layers` scene (#491), or a caller function. */\n scene: \"chart\" | \"material-layers\" | \"material-function\" | \"reflectance-function\" | \"radiance-function\";\n}\n/** One render of a region: the CPU renderer's own setup (tables, readout, demosaic, region, callbacks) and the render's signal. */\nexport interface DisplayViewGpuPart { setup: DisplayViewSetup; signal: AbortSignal | undefined }\n/** What a GPU render returns: the CPU renderer's result shape plus the a-priori bound of its values against the reference. */\nexport interface DisplayViewGpuRenderOutput extends DisplayViewRenderResult {\n errorBound: NonNullable<ImageKernelExecution[\"errorBound\"]>;\n /** Samples whose float32 classification fell inside its bound (0 when none). */\n diagnosticUncertaintySampleCount?: number;\n /** The composite chart kernel's device probe record, when the render used the composite material module. */\n compositeProbe?: ChartCompositeProbeRecord;\n}\n/** A conformance case: returns `true` when the device agrees with the reference within the case's bound, or a sentence saying how it did not. */\nexport interface DisplayViewGpuConformanceCase { id: string; run(runtime: DisplayViewGpuRuntimeHandle, signal: AbortSignal | undefined): Promise<true | string> }\n/**\n * Internal (#481): the contract a GPU display-view renderer fulfils (#478). One instance serves one device, created by the\n * registered factory for each prepared view that acquires or shares a device. `supports` says whether the renderer covers a\n * prepared request (`true`) or why not (a sentence; the view then runs the CPU reference labelled `unsupported-on-backend`).\n * `render` renders one region on the device and must throw `ImageKernelExecutionError` with reason `device-lost` or `aborted`\n * for those two events, as the accelerator's operations do; a render that throws `unsupported-on-backend` (a request the\n * renderer finds it does not cover only when rendering) runs the CPU reference labelled with that reason, or fails with it under\n * `\"require\"`. `conformanceCases` are run after the built-in image-kernel cases before the device's first render; a failure keeps\n * the whole view on the CPU. `dispose` releases what the renderer holds on the device (#491: uploaded scene records); the session\n * calls it when the prepared view is disposed.\n */\nexport interface DisplayViewGpuRenderer {\n readonly id: string;\n supports(request: DisplayViewGpuRequest): true | string;\n render(part: DisplayViewGpuPart): Promise<DisplayViewGpuRenderOutput>;\n readonly conformanceCases?: readonly DisplayViewGpuConformanceCase[];\n dispose?(): void;\n}\nexport type DisplayViewGpuRendererFactory = (runtime: DisplayViewGpuRuntimeHandle) => DisplayViewGpuRenderer;\n\nlet rendererFactory: DisplayViewGpuRendererFactory | null = null;\n/**\n * Internal (#481): registers the renderer that `prepareDisplayView` uses for `gpu: \"auto\" | \"require\"`, and returns the one\n * registered before (null: none). #478's renderer registers itself here; tests register a fake. With none registered no device\n * is requested and every GPU request falls back (or fails) with `unsupported-on-backend`.\n */\nexport function setDisplayViewGpuRendererFactory(factory: DisplayViewGpuRendererFactory | null): DisplayViewGpuRendererFactory | null {\n if (factory !== null && typeof factory !== \"function\") throw new InvalidConfigurationError(\"setDisplayViewGpuRendererFactory expects a function or null.\");\n const previous = rendererFactory;\n rendererFactory = factory;\n return previous;\n}\n/** Internal: the registered factory. */\nexport function displayViewGpuRendererFactory(): DisplayViewGpuRendererFactory | null { return rendererFactory; }\n"]}
|
|
1
|
+
{"version":3,"file":"display-view-gpu.js","sourceRoot":"","sources":["../../src/facade/display-view-gpu.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * #481: how a prepared display view chooses between a WebGPU preview renderer and the CPU reference, and how a render labels\n * which ran. This module holds the option, the label and the renderer contract and imports nothing from the GPU code, so a\n * bundle that never asks for the GPU (`gpu: \"off\"`, the default) does not contain it; the device handling lives in\n * `display-view-gpu-session.ts`, loaded on demand by `prepareDisplayView` when `gpu` is `\"auto\"` or `\"require\"`.\n *\n * The vocabulary is the image-kernel accelerator's (`createImageKernelAccelerator`, docs/WEBGPU.md): `\"auto\"` is\n * `backend: \"webgpu-f32\"` with `fallback: \"cpu-reference\"`, `\"require\"` is `fallback: \"fail\"`, `\"off\"` is\n * `backend: \"cpu-reference\"`. The render's `diagnostics.fast.execution` names the backend that ran, the fallback reason and the\n * bound in the fields of `ImageKernelExecution`, plus the adapter and the run-time conformance check.\n *\n * No GPU display-view renderer exists yet (#478, #479): until one registers itself through {@link setDisplayViewGpuRendererFactory},\n * `\"auto\"` runs the CPU reference labelled `unsupported-on-backend` without touching a device, and `\"require\"` fails with that reason.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport type { ChartCompositeProbeRecord, ImageKernelAdapterDescription, ImageKernelBackend, ImageKernelExecution, ImageKernelFallbackReason } from \"../gpu/image-kernel-execution.js\";\nimport type { DisplayViewRenderResult, DisplayViewSetup } from \"./display-view.js\";\nimport type { SimulateCaptureFastReport } from \"./simulate-capture.js\";\n\n/**\n * 2.11 (#481): whether a prepared display view may render on the GPU. `\"off\"` (the default) is the CPU reference, today's\n * behaviour byte for byte. `\"auto\"` renders on WebGPU when a conforming device is available and the request is supported, and\n * otherwise runs the CPU reference and says why. `\"require\"` fails instead of falling back. In the accelerator's words: `\"auto\"`\n * is `backend: \"webgpu-f32\"` with `fallback: \"cpu-reference\"`, `\"require\"` is `fallback: \"fail\"`, `\"off\"` is `backend: \"cpu-reference\"`.\n */\nexport type DisplayViewGpuMode = \"off\" | \"auto\" | \"require\";\n\n/** 2.11 (#481): the second argument of `prepareDisplayView`. */\nexport interface PrepareDisplayViewOptions {\n /** See {@link DisplayViewGpuMode}. Default `\"off\"`. */\n gpu?: DisplayViewGpuMode;\n /**\n * Where the device comes from, with `gpu: \"auto\"` or `\"require\"`: a WebGPU entry point (a worker's `navigator.gpu`), or an\n * `ImageKernelAccelerator` whose device the view shares (the accelerator keeps ownership; `dispose()` of the prepared view\n * leaves it alone). Without it the engine acquires a device from `globalThis.navigator.gpu` and owns it until `dispose()`.\n * Refused with `gpu: \"off\"`.\n */\n gpuDevice?: unknown;\n}\n\n/** The parsed form of {@link PrepareDisplayViewOptions}. @internal */\nexport interface ParsedPrepareDisplayViewOptions { gpu: DisplayViewGpuMode; gpuDevice: unknown }\n\n/** Internal: validates the second argument of `prepareDisplayView`. */\nexport function parsePrepareDisplayViewOptions(value: unknown): ParsedPrepareDisplayViewOptions {\n if (value === undefined) return { gpu: \"off\", gpuDevice: undefined };\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) throw new InvalidConfigurationError(\"prepareDisplayView options must be an object { gpu, gpuDevice }.\");\n for (const key of Object.keys(value)) if (key !== \"gpu\" && key !== \"gpuDevice\") throw new InvalidConfigurationError(\"Unknown prepareDisplayView options field: \" + key + \".\");\n const { gpu, gpuDevice } = value as Record<string, unknown>;\n const mode: DisplayViewGpuMode = gpu === undefined ? \"off\" : gpu as DisplayViewGpuMode;\n if (mode !== \"off\" && mode !== \"auto\" && mode !== \"require\") throw new InvalidConfigurationError(\"prepareDisplayView options.gpu must be \\\"off\\\", \\\"auto\\\" or \\\"require\\\".\");\n if (gpuDevice !== undefined && (typeof gpuDevice !== \"object\" || gpuDevice === null)) throw new InvalidConfigurationError(\"prepareDisplayView options.gpuDevice must be a WebGPU entry point (navigator.gpu) or an ImageKernelAccelerator.\");\n if (gpuDevice !== undefined && mode === \"off\") throw new InvalidConfigurationError(\"prepareDisplayView options.gpuDevice needs gpu \\\"auto\\\" or \\\"require\\\".\");\n return { gpu: mode, gpuDevice };\n}\n\n/**\n * 2.11 (#481): why a display view that asked for the GPU (`gpu: \"auto\"`) ran the CPU reference. The accelerator's acquisition\n * reasons, plus: `unsupported-on-backend` (no GPU display-view renderer exists in this version, or it does not support the\n * request), `conformance-failed` (the device failed the run-time self-check before the view's first GPU render), `device-lost`\n * (the device was lost; the rest of the view runs on the CPU) and `disposed` (the prepared view was disposed).\n */\nexport type DisplayViewGpuFallbackReason = ImageKernelFallbackReason | \"unsupported-on-backend\" | \"conformance-failed\" | \"device-lost\" | \"disposed\";\n\n/** 2.11 (#481): the run-time conformance self-check of a device, run once before the view's first GPU render. */\nexport interface DisplayViewGpuConformance {\n /** The ids of the cases run, in order (the built-in image-kernel cases, then the renderer's own). */\n cases: readonly string[];\n passed: boolean;\n /** The first case that failed, or null. */\n failedCase: string | null;\n /** What the failed case reported, or null. */\n detail: string | null;\n}\n\n/**\n * 2.11 (#481): where a display view's render ran, in the words of the image-kernel execution record (`ImageKernelExecution`):\n * `backend` names the path that ran (`cpu-reference`, the float64 engine reference, or `webgpu-f32`, a float32 approximation\n * within `errorBound`), `requestedBackend` what `gpu` asked for, and `fallbackReason` why a request for the GPU ran the CPU.\n * `adapter` describes the device's adapter whenever one was involved, also when the view then fell back; `conformance` is\n * the device's self-check once it has run. A CPU render keeps `assurance: \"engine-reference\"` and `fast: false`.\n */\nexport interface DisplayViewExecution extends Omit<ImageKernelExecution, \"fallbackReason\"> {\n /** The `gpu` option the view was prepared with. */\n gpu: DisplayViewGpuMode;\n fallbackReason: DisplayViewGpuFallbackReason | null;\n adapter: ImageKernelAdapterDescription | null;\n conformance: DisplayViewGpuConformance | null;\n /**\n * 2.11: the composite chart kernel's device probe when this render needed it (composite charts, the 2.3 elements and\n * `material-layers` scenes): the device class and the product path the kernel ran with, or, on a refusal (`fallbackReason`\n * `unsupported-on-backend`), why. Null when the render did not run the probe (the 2.0 presets, `gpu: \"off\"`).\n */\n compositeProbe: ChartCompositeProbeRecord | null;\n}\n\n/** 2.11 (#481): `diagnostics.fast` of a display view: the capture's report plus where the render ran. */\nexport interface DisplayViewFastReport extends SimulateCaptureFastReport {\n /** Where this render ran (see {@link DisplayViewExecution}). `assurance` above follows it. */\n execution: DisplayViewExecution;\n}\n\nconst CPU_LIMITATIONS = /* @__PURE__ */ Object.freeze([\"Float64 engine reference execution; results are the reference by definition\"]);\n\n/** Internal: the execution record of a display view rendered on the CPU reference. `requested` names what `gpu` asked for. */\nexport function cpuDisplayViewExecution(gpu: DisplayViewGpuMode, fallbackReason: DisplayViewGpuFallbackReason | null, adapter: ImageKernelAdapterDescription | null,\n conformance: DisplayViewGpuConformance | null, detail?: string, compositeProbe: ChartCompositeProbeRecord | null = null): DisplayViewExecution {\n const requestedBackend: ImageKernelBackend = gpu === \"off\" ? \"cpu-reference\" : \"webgpu-f32\";\n const limitations = detail === undefined ? CPU_LIMITATIONS : Object.freeze([...CPU_LIMITATIONS, \"WebGPU was requested (gpu: \\\"\" + gpu + \"\\\") and the CPU reference ran: \" + detail]);\n return Object.freeze({ gpu, backend: \"cpu-reference\", requestedBackend, fallbackReason, arithmetic: \"float64\", assurance: \"engine-reference\", fast: false,\n bitIdenticalToReference: true, errorBound: null, diagnosticsExact: true, diagnosticUncertaintySampleCount: 0, limitations, adapter, conformance, compositeProbe });\n}\n\n// ---------------------------------------------------------------------------------------------------------------\n// The renderer contract (#478 implements it; until then the only implementation is a test fake).\n\n/**\n * Internal (#481): the device a renderer or conformance case runs on. It is the engine's `WebGpuRuntime` object\n * (`src/gpu/webgpu-runtime.ts`: `device`, `guard`, `destroy` and the rest), seen here through its WebGPU-free members only so\n * that no WebGPU type reaches the published declarations (docs/WEBGPU.md); a renderer in the engine casts it to `WebGpuRuntime`.\n */\nexport interface DisplayViewGpuRuntimeHandle {\n readonly adapter: ImageKernelAdapterDescription | null;\n readonly maximumStorageBindingBytes: number;\n readonly maximumWorkgroupsPerDimension: number;\n isLost(): boolean;\n}\n\n/** What a prepared request asks of a GPU renderer (`supports`): the options that shape a render. */\nexport interface DisplayViewGpuRequest {\n ahd: boolean;\n diffraction: boolean;\n antiAliasing: boolean;\n /** Pixel-aperture samples per axis (1: centre sampling). */\n boxSamples: number;\n toneCurve: \"identity\" | \"positive-reinhard-per-channel\";\n /**\n * #492: true when `lens.defocus` needs the defocus disc (out of focus): the expected signal then carries the disc, or each\n * node's diffraction kernel convolved with it, as site kernels (#492 step 2b), which the engine's renderer gathers in its\n * Quality site pass (step 2c). Absent or false otherwise.\n */\n defocus?: boolean;\n /** The scene's form: an engine chart, a declared `material-layers` scene (#491), or a caller function. */\n scene: \"chart\" | \"material-layers\" | \"material-function\" | \"reflectance-function\" | \"radiance-function\";\n}\n/** One render of a region: the CPU renderer's own setup (tables, readout, demosaic, region, callbacks) and the render's signal. */\nexport interface DisplayViewGpuPart { setup: DisplayViewSetup; signal: AbortSignal | undefined }\n/** What a GPU render returns: the CPU renderer's result shape plus the a-priori bound of its values against the reference. */\nexport interface DisplayViewGpuRenderOutput extends DisplayViewRenderResult {\n errorBound: NonNullable<ImageKernelExecution[\"errorBound\"]>;\n /** Samples whose float32 classification fell inside its bound (0 when none). */\n diagnosticUncertaintySampleCount?: number;\n /** The composite chart kernel's device probe record, when the render used the composite material module. */\n compositeProbe?: ChartCompositeProbeRecord;\n}\n/** A conformance case: returns `true` when the device agrees with the reference within the case's bound, or a sentence saying how it did not. */\nexport interface DisplayViewGpuConformanceCase { id: string; run(runtime: DisplayViewGpuRuntimeHandle, signal: AbortSignal | undefined): Promise<true | string> }\n/**\n * Internal (#481): the contract a GPU display-view renderer fulfils (#478). One instance serves one device, created by the\n * registered factory for each prepared view that acquires or shares a device. `supports` says whether the renderer covers a\n * prepared request (`true`) or why not (a sentence; the view then runs the CPU reference labelled `unsupported-on-backend`).\n * `render` renders one region on the device and must throw `ImageKernelExecutionError` with reason `device-lost` or `aborted`\n * for those two events, as the accelerator's operations do; a render that throws `unsupported-on-backend` (a request the\n * renderer finds it does not cover only when rendering) runs the CPU reference labelled with that reason, or fails with it under\n * `\"require\"`. `conformanceCases` are run after the built-in image-kernel cases before the device's first render; a failure keeps\n * the whole view on the CPU. `dispose` releases what the renderer holds on the device (#491: uploaded scene records); the session\n * calls it when the prepared view is disposed.\n */\nexport interface DisplayViewGpuRenderer {\n readonly id: string;\n supports(request: DisplayViewGpuRequest): true | string;\n render(part: DisplayViewGpuPart): Promise<DisplayViewGpuRenderOutput>;\n readonly conformanceCases?: readonly DisplayViewGpuConformanceCase[];\n dispose?(): void;\n}\nexport type DisplayViewGpuRendererFactory = (runtime: DisplayViewGpuRuntimeHandle) => DisplayViewGpuRenderer;\n\nlet rendererFactory: DisplayViewGpuRendererFactory | null = null;\n/**\n * Internal (#481): registers the renderer that `prepareDisplayView` uses for `gpu: \"auto\" | \"require\"`, and returns the one\n * registered before (null: none). #478's renderer registers itself here; tests register a fake. With none registered no device\n * is requested and every GPU request falls back (or fails) with `unsupported-on-backend`.\n */\nexport function setDisplayViewGpuRendererFactory(factory: DisplayViewGpuRendererFactory | null): DisplayViewGpuRendererFactory | null {\n if (factory !== null && typeof factory !== \"function\") throw new InvalidConfigurationError(\"setDisplayViewGpuRendererFactory expects a function or null.\");\n const previous = rendererFactory;\n rendererFactory = factory;\n return previous;\n}\n/** Internal: the registered factory. */\nexport function displayViewGpuRendererFactory(): DisplayViewGpuRendererFactory | null { return rendererFactory; }\n"]}
|
|
@@ -255,6 +255,33 @@ export declare function computeDisplayViewCorrectionStates(setup: DisplayViewCor
|
|
|
255
255
|
* evaluated while the stratified estimator takes a quarter of its samples per axis where the pilot finds no detail.
|
|
256
256
|
*/
|
|
257
257
|
export declare const EXACT_AREA_MEAN_MAX_PIXELS = 25;
|
|
258
|
+
/**
|
|
259
|
+
* createAhdDemosaicTask's steps at the centre pixel of an 11 × 11 patch (patch (dy + 5)·11 + dx + 5, normalized site values):
|
|
260
|
+
* `choose(phase)` fills the two candidates within 2 sites (`horizontal`, `vertical`: (dy + 2)·5 + dx + 2, three channels) and
|
|
261
|
+
* returns the centre's direction, 0 horizontal, 1 vertical, 2 equal homogeneity (both averaged). Greens are read by flat
|
|
262
|
+
* index (dy + 3)·7 + dx + 3; every value is formed with the same operations in the same order as the steps themselves,
|
|
263
|
+
* except that CIELAB's cube root is `portableCbrt` (within 1 ulp of Math.cbrt) and squares are products, so the result has
|
|
264
|
+
* the same bits in every JavaScript engine. (The task keeps its intermediate planes in float32; these are binary64.)
|
|
265
|
+
*/
|
|
266
|
+
export declare function createAhdCentreSteps(labMatrix: readonly (readonly number[])[], patch: Float64Array): {
|
|
267
|
+
horizontal: Float64Array;
|
|
268
|
+
vertical: Float64Array;
|
|
269
|
+
choose(phase: number): number;
|
|
270
|
+
};
|
|
271
|
+
/**
|
|
272
|
+
* #457: AHD's direction at real pixels of the noise-free mosaic, as `createAhdDemosaicTask` computes it on the whole raster
|
|
273
|
+
* (every neighbour read at its reflect-101 position, so a position's greens, candidates, CIELAB and homogeneity are those of
|
|
274
|
+
* the task's planes), with each per-position quantity computed once and kept in rings of native rows. `direction(x, y)` is 0
|
|
275
|
+
* horizontal, 1 vertical, 2 equal homogeneity; `site(x, y)` gives the normalized expected value of an in-raster site, clipped
|
|
276
|
+
* at white. The kept columns are [x0, x0 + columns), set by `origin(x0)` (which also forgets every kept value); they must hold
|
|
277
|
+
* every real pixel asked about and 5 sites around it, clipped to the raster. `rows` is a power of two at least the native rows
|
|
278
|
+
* the real pixels asked about between two `origin` calls span plus 10. The arithmetic is the task's, in binary64 (the task
|
|
279
|
+
* stores its planes in float32), with `portableCbrt` and products for squares, as `createAhdCentreSteps`.
|
|
280
|
+
*/
|
|
281
|
+
export declare function createAhdDirectionPlane(labMatrix: readonly (readonly number[])[], nativeWidth: number, nativeHeight: number, columns: number, rows: number, site: (x: number, y: number) => number): {
|
|
282
|
+
origin(x0: number): void;
|
|
283
|
+
direction(x: number, y: number): number;
|
|
284
|
+
};
|
|
258
285
|
/** Renders the display view (docs/DISPLAY_VIEW.md). */
|
|
259
286
|
export declare function renderDisplayView(setup: DisplayViewSetup): Promise<DisplayViewRenderResult>;
|
|
260
287
|
/**
|