@photivra/engine 2.2.1 → 2.3.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 +16 -1
- package/CITATION.cff +1 -1
- package/README.md +6 -6
- package/SECURITY.md +1 -1
- package/dist/capture/native-environment-raw.d.ts +18 -0
- package/dist/capture/native-environment-raw.js +17 -1
- package/dist/capture/native-environment-raw.js.map +1 -1
- package/dist/capture/native-raw.d.ts +3 -0
- package/dist/capture/native-raw.js +8 -5
- package/dist/capture/native-raw.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.d.ts +46 -0
- package/dist/equipment/generic-prime-lenses.js +59 -0
- package/dist/equipment/generic-prime-lenses.js.map +1 -0
- package/dist/facade/chart-scenes.d.ts +270 -1
- package/dist/facade/chart-scenes.js +443 -17
- package/dist/facade/chart-scenes.js.map +1 -1
- package/dist/facade/scene-radiance.d.ts +47 -0
- package/dist/facade/scene-radiance.js +65 -5
- package/dist/facade/scene-radiance.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +151 -4
- package/dist/facade/simulate-capture.js +296 -55
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/facade/subject-framing.d.ts +55 -0
- package/dist/facade/subject-framing.js +66 -0
- package/dist/facade/subject-framing.js.map +1 -0
- package/dist/gpu/chart-radiance-gpu.d.ts +8 -0
- package/dist/gpu/chart-radiance-gpu.js +20 -1
- package/dist/gpu/chart-radiance-gpu.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/docs/API_REFERENCE.md +48 -1
- package/docs/QUICK_START.md +264 -3
- package/docs/api/core-version.md +1 -1
- package/docs/api/equipment-generic-prime-lenses.md +85 -0
- package/docs/api/exports.json +167 -2
- package/docs/api/facade-chart-scenes.md +280 -4
- package/docs/api/facade-scene-radiance.md +42 -0
- package/docs/api/facade-simulate-capture.md +107 -2
- package/docs/api/facade-subject-framing.md +72 -0
- package/package.json +1 -1
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type GenericPrimeLens } from "../equipment/generic-prime-lenses.js";
|
|
2
|
+
import type { SimulateCaptureAssumption } from "./simulate-capture.js";
|
|
3
|
+
/** How the chart fits the frame: `contain` (default; the whole chart is visible and its limiting side touches the frame), `width`, `height` or `cover` (the chart fills the frame and is cropped on its other side). */
|
|
4
|
+
export type SubjectFramingFit = "contain" | "width" | "height" | "cover";
|
|
5
|
+
export interface CalculateSubjectDistanceForFramingInput {
|
|
6
|
+
/** Active sensor (or simulated frame) size, mm. */
|
|
7
|
+
sensor: {
|
|
8
|
+
widthMm: number;
|
|
9
|
+
heightMm: number;
|
|
10
|
+
};
|
|
11
|
+
/** Physical focal length, mm. Give exactly one of this and `equivalentFocalLengthMm`. */
|
|
12
|
+
focalLengthMm?: number;
|
|
13
|
+
/** Full-frame-equivalent focal length (diagonal crop factor); a generic prime's value also reports that lens. */
|
|
14
|
+
equivalentFocalLengthMm?: number;
|
|
15
|
+
/** Chart size as for `simulateCapture` `chartSize`: heightM defaults to widthM × the sensor aspect (height / width). */
|
|
16
|
+
chart: {
|
|
17
|
+
widthM: number;
|
|
18
|
+
heightM?: number;
|
|
19
|
+
};
|
|
20
|
+
fit?: SubjectFramingFit;
|
|
21
|
+
}
|
|
22
|
+
export interface SubjectFraming {
|
|
23
|
+
/** Distance from the lens to the chart plane, metres: f·(1 + 1/m). */
|
|
24
|
+
subjectDistanceM: number;
|
|
25
|
+
/** Image size ÷ object size, f/(d − f). */
|
|
26
|
+
magnification: number;
|
|
27
|
+
/** Thin-lens image distance f·(1 + m), mm. */
|
|
28
|
+
imageDistanceMm: number;
|
|
29
|
+
focalLengthMm: number;
|
|
30
|
+
equivalentFocalLengthMm: number;
|
|
31
|
+
cropFactor35Mm: number;
|
|
32
|
+
chart: {
|
|
33
|
+
widthM: number;
|
|
34
|
+
heightM: number;
|
|
35
|
+
};
|
|
36
|
+
fit: SubjectFramingFit;
|
|
37
|
+
/** Plane area the frame covers at that distance, metres. */
|
|
38
|
+
framedWidthM: number;
|
|
39
|
+
framedHeightM: number;
|
|
40
|
+
/** Fraction of the frame width and height the chart covers (1 on the fitted side; above 1 means cropped). */
|
|
41
|
+
coverage: {
|
|
42
|
+
frameWidthFraction: number;
|
|
43
|
+
frameHeightFraction: number;
|
|
44
|
+
};
|
|
45
|
+
/** The generic prime of this equivalent focal length, when there is one. */
|
|
46
|
+
prime: GenericPrimeLens | null;
|
|
47
|
+
/** The generic prime rule max(0.10 m, f·(1 + 1/0.15)) at this focal length (the prime's own value when there is one). */
|
|
48
|
+
minimumFocusDistanceM: number;
|
|
49
|
+
/** True when the fit distance is closer than the minimum focus distance: the chart cannot be framed this way. */
|
|
50
|
+
belowMinimumFocus: boolean;
|
|
51
|
+
scientificStatus: "approximation";
|
|
52
|
+
assumptions: readonly SimulateCaptureAssumption[];
|
|
53
|
+
}
|
|
54
|
+
/** The subject distance that fits a chart of a given physical size to the frame, with magnification, coverage and the minimum-focus check (2.3). */
|
|
55
|
+
export declare function calculateSubjectDistanceForFraming(input: CalculateSubjectDistanceForFramingInput): SubjectFraming;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/**
|
|
3
|
+
* Subject distance for framing a chart (2.3). Thin lens: an object at distance d from a lens of focal length f
|
|
4
|
+
* images at v = f·d/(d − f) with magnification m = v/d = f/(d − f), so the distance for a magnification m is
|
|
5
|
+
* d = f·(1 + 1/m). This is the same framing the capture facade uses (`scene.framing`, `chartSize`), so a chart
|
|
6
|
+
* placed at the returned distance with `chartSize` fills the frame as reported.
|
|
7
|
+
* @see docs/QUICK_START.md, "Fitting a chart to the frame".
|
|
8
|
+
*/
|
|
9
|
+
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
10
|
+
import { requireInputObject } from "../core/record-validation.js";
|
|
11
|
+
import { calculateEquivalentFocalLength35Mm } from "../camera/equivalent-focal-length.js";
|
|
12
|
+
import { calculateGenericPrimeMinimumFocusDistanceM, resolveGenericPrimeLens, GENERIC_PRIME_EQUIVALENT_FOCAL_LENGTHS_MM } from "../equipment/generic-prime-lenses.js";
|
|
13
|
+
function positive(value, name) {
|
|
14
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0 || value > 1e7)
|
|
15
|
+
throw new InvalidConfigurationError(name + " must be a positive finite number.");
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
/** The subject distance that fits a chart of a given physical size to the frame, with magnification, coverage and the minimum-focus check (2.3). */
|
|
19
|
+
export function calculateSubjectDistanceForFraming(input) {
|
|
20
|
+
requireInputObject(input, "calculateSubjectDistanceForFraming input");
|
|
21
|
+
for (const key of Object.keys(input))
|
|
22
|
+
if (!["sensor", "focalLengthMm", "equivalentFocalLengthMm", "chart", "fit"].includes(key))
|
|
23
|
+
throw new InvalidConfigurationError("calculateSubjectDistanceForFraming input has unknown field \"" + key + "\".");
|
|
24
|
+
requireInputObject(input.sensor, "sensor");
|
|
25
|
+
requireInputObject(input.chart, "chart");
|
|
26
|
+
for (const key of Object.keys(input.sensor))
|
|
27
|
+
if (key !== "widthMm" && key !== "heightMm")
|
|
28
|
+
throw new InvalidConfigurationError("Unknown sensor field: " + key + ".");
|
|
29
|
+
for (const key of Object.keys(input.chart))
|
|
30
|
+
if (key !== "widthM" && key !== "heightM")
|
|
31
|
+
throw new InvalidConfigurationError("Unknown chart field: " + key + ".");
|
|
32
|
+
const sensorW = positive(input.sensor.widthMm, "sensor.widthMm"), sensorH = positive(input.sensor.heightMm, "sensor.heightMm");
|
|
33
|
+
if ((input.focalLengthMm === undefined) === (input.equivalentFocalLengthMm === undefined))
|
|
34
|
+
throw new InvalidConfigurationError("Give exactly one of focalLengthMm and equivalentFocalLengthMm.");
|
|
35
|
+
const crop = calculateEquivalentFocalLength35Mm({ focalLengthMm: 1, activeImagingArea: { widthMm: sensorW, heightMm: sensorH } }).value.cropFactor35Mm;
|
|
36
|
+
const assumptions = [];
|
|
37
|
+
const equivalent = input.equivalentFocalLengthMm === undefined ? positive(input.focalLengthMm, "focalLengthMm") * crop : positive(input.equivalentFocalLengthMm, "equivalentFocalLengthMm");
|
|
38
|
+
const focalLengthMm = input.focalLengthMm === undefined ? equivalent / crop : input.focalLengthMm;
|
|
39
|
+
const prime = GENERIC_PRIME_EQUIVALENT_FOCAL_LENGTHS_MM.includes(equivalent) && input.equivalentFocalLengthMm !== undefined ?
|
|
40
|
+
resolveGenericPrimeLens({ equivalentFocalLengthMm: equivalent, activeImagingArea: { widthMm: sensorW, heightMm: sensorH } }) : null;
|
|
41
|
+
const widthM = positive(input.chart.widthM, "chart.widthM");
|
|
42
|
+
const heightM = input.chart.heightM === undefined ? widthM * sensorH / sensorW : positive(input.chart.heightM, "chart.heightM");
|
|
43
|
+
if (input.chart.heightM === undefined)
|
|
44
|
+
assumptions.push({ id: "chart.heightM", kind: "default", value: heightM, explanation: "The chart has the sensor's shape: height = width × sensor height / sensor width." });
|
|
45
|
+
const fit = input.fit ?? "contain";
|
|
46
|
+
if (!["contain", "width", "height", "cover"].includes(fit))
|
|
47
|
+
throw new InvalidConfigurationError("fit must be contain, width, height or cover.");
|
|
48
|
+
if (input.fit === undefined)
|
|
49
|
+
assumptions.push({ id: "fit", kind: "default", value: "contain", explanation: "The whole chart is visible: the side whose chart-to-sensor ratio is larger (the limiting side) fills the frame." });
|
|
50
|
+
// Magnification that makes each chart side exactly fill the matching sensor side.
|
|
51
|
+
const mWidth = sensorW / (widthM * 1000), mHeight = sensorH / (heightM * 1000);
|
|
52
|
+
const m = fit === "width" ? mWidth : fit === "height" ? mHeight : fit === "contain" ? Math.min(mWidth, mHeight) : Math.max(mWidth, mHeight);
|
|
53
|
+
const f = focalLengthMm / 1000, subjectDistanceM = f * (1 + 1 / m), minimumFocusDistanceM = prime ? prime.minimumFocusDistanceM : calculateGenericPrimeMinimumFocusDistanceM(focalLengthMm);
|
|
54
|
+
assumptions.push({ id: "model.thin-lens-framing", kind: "model", value: { magnification: m, subjectDistanceM },
|
|
55
|
+
explanation: "Thin lens focused on the chart plane: d = f·(1 + 1/m), image distance v = f·(1 + m), the same framing simulateCapture uses. Distances are from the lens; pupil positions, focus breathing and distortion are not modelled." });
|
|
56
|
+
assumptions.push({ id: "minimumFocus", kind: "model", value: { minimumFocusDistanceM, rule: "max(0.10 m, f·(1 + 1/0.15))" },
|
|
57
|
+
explanation: "The generic prime family's minimum focus rule (a thin-lens approximation, not a real lens)" + (prime ? " for " + prime.lensId : " applied to this focal length") + "." });
|
|
58
|
+
if (input.equivalentFocalLengthMm !== undefined)
|
|
59
|
+
assumptions.push({ id: "focalLengthMm", kind: "derived", value: focalLengthMm,
|
|
60
|
+
explanation: "Equivalent focal length ÷ diagonal crop factor " + crop + " (calculateEquivalentFocalLength35Mm, 36 × 24 mm reference)." });
|
|
61
|
+
return Object.freeze({ subjectDistanceM, magnification: m, imageDistanceMm: focalLengthMm * (1 + m), focalLengthMm, equivalentFocalLengthMm: equivalent, cropFactor35Mm: crop,
|
|
62
|
+
chart: { widthM, heightM }, fit, framedWidthM: sensorW / 1000 / m, framedHeightM: sensorH / 1000 / m,
|
|
63
|
+
coverage: { frameWidthFraction: widthM * 1000 * m / sensorW, frameHeightFraction: heightM * 1000 * m / sensorH }, prime, minimumFocusDistanceM,
|
|
64
|
+
belowMinimumFocus: subjectDistanceM < minimumFocusDistanceM, scientificStatus: "approximation", assumptions: Object.freeze(assumptions.map((a) => Object.freeze(a))) });
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=subject-framing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subject-framing.js","sourceRoot":"","sources":["../../src/facade/subject-framing.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Subject distance for framing a chart (2.3). Thin lens: an object at distance d from a lens of focal length f\n * images at v = f·d/(d − f) with magnification m = v/d = f/(d − f), so the distance for a magnification m is\n * d = f·(1 + 1/m). This is the same framing the capture facade uses (`scene.framing`, `chartSize`), so a chart\n * placed at the returned distance with `chartSize` fills the frame as reported.\n * @see docs/QUICK_START.md, \"Fitting a chart to the frame\".\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { requireInputObject } from \"../core/record-validation.js\";\nimport { calculateEquivalentFocalLength35Mm } from \"../camera/equivalent-focal-length.js\";\nimport { calculateGenericPrimeMinimumFocusDistanceM, resolveGenericPrimeLens, GENERIC_PRIME_EQUIVALENT_FOCAL_LENGTHS_MM, type GenericPrimeLens } from \"../equipment/generic-prime-lenses.js\";\nimport type { SimulateCaptureAssumption } from \"./simulate-capture.js\";\n\n/** How the chart fits the frame: `contain` (default; the whole chart is visible and its limiting side touches the frame), `width`, `height` or `cover` (the chart fills the frame and is cropped on its other side). */\nexport type SubjectFramingFit = \"contain\" | \"width\" | \"height\" | \"cover\";\n\nexport interface CalculateSubjectDistanceForFramingInput {\n /** Active sensor (or simulated frame) size, mm. */\n sensor: { widthMm: number; heightMm: number };\n /** Physical focal length, mm. Give exactly one of this and `equivalentFocalLengthMm`. */\n focalLengthMm?: number;\n /** Full-frame-equivalent focal length (diagonal crop factor); a generic prime's value also reports that lens. */\n equivalentFocalLengthMm?: number;\n /** Chart size as for `simulateCapture` `chartSize`: heightM defaults to widthM × the sensor aspect (height / width). */\n chart: { widthM: number; heightM?: number };\n fit?: SubjectFramingFit;\n}\n\nexport interface SubjectFraming {\n /** Distance from the lens to the chart plane, metres: f·(1 + 1/m). */\n subjectDistanceM: number;\n /** Image size ÷ object size, f/(d − f). */\n magnification: number;\n /** Thin-lens image distance f·(1 + m), mm. */\n imageDistanceMm: number;\n focalLengthMm: number;\n equivalentFocalLengthMm: number;\n cropFactor35Mm: number;\n chart: { widthM: number; heightM: number };\n fit: SubjectFramingFit;\n /** Plane area the frame covers at that distance, metres. */\n framedWidthM: number;\n framedHeightM: number;\n /** Fraction of the frame width and height the chart covers (1 on the fitted side; above 1 means cropped). */\n coverage: { frameWidthFraction: number; frameHeightFraction: number };\n /** The generic prime of this equivalent focal length, when there is one. */\n prime: GenericPrimeLens | null;\n /** The generic prime rule max(0.10 m, f·(1 + 1/0.15)) at this focal length (the prime's own value when there is one). */\n minimumFocusDistanceM: number;\n /** True when the fit distance is closer than the minimum focus distance: the chart cannot be framed this way. */\n belowMinimumFocus: boolean;\n scientificStatus: \"approximation\";\n assumptions: readonly SimulateCaptureAssumption[];\n}\n\nfunction positive(value: unknown, name: string): number {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0 || value > 1e7) throw new InvalidConfigurationError(name + \" must be a positive finite number.\");\n return value;\n}\n\n/** The subject distance that fits a chart of a given physical size to the frame, with magnification, coverage and the minimum-focus check (2.3). */\nexport function calculateSubjectDistanceForFraming(input: CalculateSubjectDistanceForFramingInput): SubjectFraming {\n requireInputObject(input, \"calculateSubjectDistanceForFraming input\");\n for (const key of Object.keys(input)) if (![\"sensor\", \"focalLengthMm\", \"equivalentFocalLengthMm\", \"chart\", \"fit\"].includes(key))\n throw new InvalidConfigurationError(\"calculateSubjectDistanceForFraming input has unknown field \\\"\" + key + \"\\\".\");\n requireInputObject(input.sensor, \"sensor\");\n requireInputObject(input.chart, \"chart\");\n for (const key of Object.keys(input.sensor)) if (key !== \"widthMm\" && key !== \"heightMm\") throw new InvalidConfigurationError(\"Unknown sensor field: \" + key + \".\");\n for (const key of Object.keys(input.chart)) if (key !== \"widthM\" && key !== \"heightM\") throw new InvalidConfigurationError(\"Unknown chart field: \" + key + \".\");\n const sensorW = positive(input.sensor.widthMm, \"sensor.widthMm\"), sensorH = positive(input.sensor.heightMm, \"sensor.heightMm\");\n if ((input.focalLengthMm === undefined) === (input.equivalentFocalLengthMm === undefined)) throw new InvalidConfigurationError(\"Give exactly one of focalLengthMm and equivalentFocalLengthMm.\");\n const crop = calculateEquivalentFocalLength35Mm({ focalLengthMm: 1, activeImagingArea: { widthMm: sensorW, heightMm: sensorH } }).value.cropFactor35Mm;\n const assumptions: SimulateCaptureAssumption[] = [];\n const equivalent = input.equivalentFocalLengthMm === undefined ? positive(input.focalLengthMm, \"focalLengthMm\") * crop : positive(input.equivalentFocalLengthMm, \"equivalentFocalLengthMm\");\n const focalLengthMm = input.focalLengthMm === undefined ? equivalent / crop : input.focalLengthMm;\n const prime = (GENERIC_PRIME_EQUIVALENT_FOCAL_LENGTHS_MM as readonly number[]).includes(equivalent) && input.equivalentFocalLengthMm !== undefined ?\n resolveGenericPrimeLens({ equivalentFocalLengthMm: equivalent, activeImagingArea: { widthMm: sensorW, heightMm: sensorH } }) : null;\n const widthM = positive(input.chart.widthM, \"chart.widthM\");\n const heightM = input.chart.heightM === undefined ? widthM * sensorH / sensorW : positive(input.chart.heightM, \"chart.heightM\");\n if (input.chart.heightM === undefined) assumptions.push({ id: \"chart.heightM\", kind: \"default\", value: heightM, explanation: \"The chart has the sensor's shape: height = width × sensor height / sensor width.\" });\n const fit = input.fit ?? \"contain\";\n if (![\"contain\", \"width\", \"height\", \"cover\"].includes(fit)) throw new InvalidConfigurationError(\"fit must be contain, width, height or cover.\");\n if (input.fit === undefined) assumptions.push({ id: \"fit\", kind: \"default\", value: \"contain\", explanation: \"The whole chart is visible: the side whose chart-to-sensor ratio is larger (the limiting side) fills the frame.\" });\n // Magnification that makes each chart side exactly fill the matching sensor side.\n const mWidth = sensorW / (widthM * 1000), mHeight = sensorH / (heightM * 1000);\n const m = fit === \"width\" ? mWidth : fit === \"height\" ? mHeight : fit === \"contain\" ? Math.min(mWidth, mHeight) : Math.max(mWidth, mHeight);\n const f = focalLengthMm / 1000, subjectDistanceM = f * (1 + 1 / m), minimumFocusDistanceM = prime ? prime.minimumFocusDistanceM : calculateGenericPrimeMinimumFocusDistanceM(focalLengthMm);\n assumptions.push({ id: \"model.thin-lens-framing\", kind: \"model\", value: { magnification: m, subjectDistanceM },\n explanation: \"Thin lens focused on the chart plane: d = f·(1 + 1/m), image distance v = f·(1 + m), the same framing simulateCapture uses. Distances are from the lens; pupil positions, focus breathing and distortion are not modelled.\" });\n assumptions.push({ id: \"minimumFocus\", kind: \"model\", value: { minimumFocusDistanceM, rule: \"max(0.10 m, f·(1 + 1/0.15))\" },\n explanation: \"The generic prime family's minimum focus rule (a thin-lens approximation, not a real lens)\" + (prime ? \" for \" + prime.lensId : \" applied to this focal length\") + \".\" });\n if (input.equivalentFocalLengthMm !== undefined) assumptions.push({ id: \"focalLengthMm\", kind: \"derived\", value: focalLengthMm,\n explanation: \"Equivalent focal length ÷ diagonal crop factor \" + crop + \" (calculateEquivalentFocalLength35Mm, 36 × 24 mm reference).\" });\n return Object.freeze({ subjectDistanceM, magnification: m, imageDistanceMm: focalLengthMm * (1 + m), focalLengthMm, equivalentFocalLengthMm: equivalent, cropFactor35Mm: crop,\n chart: { widthM, heightM }, fit, framedWidthM: sensorW / 1000 / m, framedHeightM: sensorH / 1000 / m,\n coverage: { frameWidthFraction: widthM * 1000 * m / sensorW, frameHeightFraction: heightM * 1000 * m / sensorH }, prime, minimumFocusDistanceM,\n belowMinimumFocus: subjectDistanceM < minimumFocusDistanceM, scientificStatus: \"approximation\" as const, assumptions: Object.freeze(assumptions.map((a) => Object.freeze(a))) });\n}\n"]}
|
|
@@ -7,6 +7,14 @@ type YieldControl = ((signal: AbortSignal) => Promise<void>) | undefined;
|
|
|
7
7
|
/** Frame-unit magnitude limit for GPU points. */
|
|
8
8
|
export declare const CHART_GPU_MAXIMUM_COORDINATE: number;
|
|
9
9
|
export declare function evaluateChartRadianceOnCpu(input: ChartRadianceBatchInput, abort: AbortController, yieldControl: YieldControl, execution: ImageKernelExecution): Promise<ChartRadianceResult>;
|
|
10
|
+
/**
|
|
11
|
+
* The preset code of a chart the WGSL kernel classifies, or undefined. The kernel covers the eight 2.0 presets
|
|
12
|
+
* (a Siemens star only with the bar profile). The 2.3 elements and composites run on `cpu-reference`: their
|
|
13
|
+
* continuous profiles need WGSL sin/cos/atan2 whose accuracy bounds would flag a large share of points for host
|
|
14
|
+
* recomputation, and dead leaves, bar groups and composites need per-element tables not yet written or measured
|
|
15
|
+
* on a device. @internal
|
|
16
|
+
*/
|
|
17
|
+
export declare function chartGpuPresetCode(plan: ChartRadianceBatchPlan): number | undefined;
|
|
10
18
|
/** Preset constants (uniform words 3–5 and floats 8–15) and the auxiliary table. @internal */
|
|
11
19
|
export declare function chartGpuConstants(plan: ChartRadianceBatchPlan): {
|
|
12
20
|
ints: [number, number, number];
|
|
@@ -35,6 +35,19 @@ export async function evaluateChartRadianceOnCpu(input, abort, yieldControl, exe
|
|
|
35
35
|
checkAbort(abort.signal);
|
|
36
36
|
return { plan, values, columns: plan.columns, execution, hostRecomputedQueryIndices: new Uint32Array(0) };
|
|
37
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* The preset code of a chart the WGSL kernel classifies, or undefined. The kernel covers the eight 2.0 presets
|
|
40
|
+
* (a Siemens star only with the bar profile). The 2.3 elements and composites run on `cpu-reference`: their
|
|
41
|
+
* continuous profiles need WGSL sin/cos/atan2 whose accuracy bounds would flag a large share of points for host
|
|
42
|
+
* recomputation, and dead leaves, bar groups and composites need per-element tables not yet written or measured
|
|
43
|
+
* on a device. @internal
|
|
44
|
+
*/
|
|
45
|
+
export function chartGpuPresetCode(plan) {
|
|
46
|
+
const preset = plan.chart.preset;
|
|
47
|
+
if (!Object.prototype.hasOwnProperty.call(CHART_PRESET_CODE, preset) || plan.chart.parameters.profile === "sine")
|
|
48
|
+
return undefined;
|
|
49
|
+
return CHART_PRESET_CODE[preset];
|
|
50
|
+
}
|
|
38
51
|
/** Preset constants (uniform words 3–5 and floats 8–15) and the auxiliary table. @internal */
|
|
39
52
|
export function chartGpuConstants(plan) {
|
|
40
53
|
const chart = plan.chart, p = chart.parameters, aspect = chart.aspect;
|
|
@@ -68,6 +81,7 @@ export function chartGpuConstants(plan) {
|
|
|
68
81
|
return { ints: [columns, rows, count], floats: [columns / 2, aspect, rows / (2 * aspect), p.gapFraction / 2, 1 - p.gapFraction / 2],
|
|
69
82
|
aux: new Float32Array(1) };
|
|
70
83
|
}
|
|
84
|
+
default: throw new ImageKernelExecutionError("unsupported-on-backend", "webgpu-f32 classifies the eight 2.0 chart presets; use cpu-reference for " + chart.preset + ".");
|
|
71
85
|
}
|
|
72
86
|
}
|
|
73
87
|
/** Per-material values in float64, with the reference's operations; a material whose spectrum fails is NaN (recomputed on the host). */
|
|
@@ -99,6 +113,11 @@ function materialTable(plan) {
|
|
|
99
113
|
}
|
|
100
114
|
export async function evaluateChartRadianceOnGpu(runtime, bandBytes, input, abort, yieldControl, pipelines) {
|
|
101
115
|
const plan = calculateChartRadianceBatchPlan(input), points = input.points.slice(), indices = input.wavelengthIndices?.slice();
|
|
116
|
+
const presetCode = chartGpuPresetCode(plan);
|
|
117
|
+
if (presetCode === undefined) {
|
|
118
|
+
throw new ImageKernelExecutionError("unsupported-on-backend", "webgpu-f32 classifies the eight 2.0 chart presets (Siemens star with the bar profile); use cpu-reference for " +
|
|
119
|
+
plan.chart.preset + (plan.chart.parameters.profile === "sine" ? " (sine profile)" : "") + ".");
|
|
120
|
+
}
|
|
102
121
|
for (let i = 0; i < points.length; i++) {
|
|
103
122
|
if (Math.abs(points[i]) > CHART_GPU_MAXIMUM_COORDINATE)
|
|
104
123
|
throw new ImageKernelExecutionError("unsupported-float32-domain", "Chart points beyond 2^20 frame units are outside the float32 domain.");
|
|
@@ -112,7 +131,7 @@ export async function evaluateChartRadianceOnGpu(runtime, bandBytes, input, abor
|
|
|
112
131
|
}
|
|
113
132
|
const params = new ArrayBuffer(64), words = new Uint32Array(params), f = new Float32Array(params);
|
|
114
133
|
words[1] = stride;
|
|
115
|
-
words[2] =
|
|
134
|
+
words[2] = presetCode;
|
|
116
135
|
words[3] = ints[0];
|
|
117
136
|
words[4] = ints[1];
|
|
118
137
|
words[5] = ints[2];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-radiance-gpu.js","sourceRoot":"","sources":["../../src/gpu/chart-radiance-gpu.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Host side of the `webgpu-f32` chart-radiance stage (#277): per-material value tables in float64 (the\n * reference's own operations), preset constants, banded dispatch, readback, and host recomputation of\n * flagged points with the reference. The float64 reference is `calculateChartRadianceBatch`\n * (facade/chart-radiance-batch.ts). Internal; the public entry point is the image-kernel accelerator.\n */\nimport { createHostYieldGate } from \"../capture/host-yield-cadence.js\";\nimport { calculateChartRadianceBatchPlan, type ChartRadianceBatchInput, type ChartRadianceBatchPlan } from \"../facade/chart-radiance-batch.js\";\nimport { calculatePointGridCenters } from \"../facade/chart-scenes.js\";\nimport { ImageKernelExecutionError, webGpuExecution, type ImageKernelExecution } from \"./image-kernel-execution.js\";\nimport type { ChartRadianceResult } from \"./image-kernel-accelerator.js\";\nimport { BUFFER_USAGE, GpuResourceScope, abortedError, linearDispatch, runComputePass, type WebGpuRuntime } from \"./webgpu-runtime.js\";\nimport { CHART_PRESET_CODE, CHART_RADIANCE_WGSL, CHART_WORKGROUP_SIZE } from \"./wgsl-chart-kernel.js\";\n\ntype PipelineSource = (label: string, code: string) => Promise<GPUComputePipeline>;\ntype YieldControl = ((signal: AbortSignal) => Promise<void>) | undefined;\n\n/** Frame-unit magnitude limit for GPU points. */\nexport const CHART_GPU_MAXIMUM_COORDINATE = 2 ** 20;\nconst FLOAT32_SAFE_MAGNITUDE = 2 ** 120;\n\n\nfunction checkAbort(signal: AbortSignal): void {\n if (signal.aborted) throw abortedError();\n}\n\nexport async function evaluateChartRadianceOnCpu(input: ChartRadianceBatchInput, abort: AbortController, yieldControl: YieldControl,\n execution: ImageKernelExecution): Promise<ChartRadianceResult> {\n const plan = calculateChartRadianceBatchPlan(input), points = input.points.slice(), indices = input.wavelengthIndices?.slice();\n const values = new Float64Array(plan.queryCount * plan.columns), gate = createHostYieldGate();\n for (let q = 0; q < plan.queryCount; q++) {\n for (let c = 0; c < plan.columns; c++) values[q * plan.columns + c] = plan.queryValue(points, indices, q, c);\n if ((q & 0xffff) === 0xffff) {\n checkAbort(abort.signal);\n if (yieldControl && gate.due()) { await yieldControl(abort.signal); gate.restart(); }\n }\n }\n checkAbort(abort.signal);\n return { plan, values, columns: plan.columns, execution, hostRecomputedQueryIndices: new Uint32Array(0) };\n}\n\n/** Preset constants (uniform words 3–5 and floats 8–15) and the auxiliary table. @internal */\nexport function chartGpuConstants(plan: ChartRadianceBatchPlan): { ints: [number, number, number]; floats: number[]; aux: Float32Array<ArrayBuffer> } {\n const chart = plan.chart, p = chart.parameters as Record<string, number>, aspect = chart.aspect;\n switch (chart.preset) {\n case \"uniform\": return { ints: [0, 0, 0], floats: [], aux: new Float32Array(1) };\n case \"slanted-edge\": {\n // The same float64 constants as resolveChartScene.\n const t = p.angleDegrees! * Math.PI / 180;\n return { ints: [0, 0, 0], floats: [Math.cos(t), Math.sin(t)], aux: new Float32Array(1) };\n }\n case \"siemens-star\": {\n const cycles = p.cycles!, r = p.radiusFraction! * aspect, aux = new Float32Array(2 * (2 * cycles + 1));\n // Sector boundaries: phase·2·cycles = k ⇔ θ = π(k/cycles − 1).\n for (let k = 0; k <= 2 * cycles; k++) { const b = Math.PI * (k / cycles - 1); aux[2 * k] = Math.cos(b); aux[2 * k + 1] = Math.sin(b); }\n return { ints: [cycles, 0, 0], floats: [r * r], aux };\n }\n case \"step-wedge\": return { ints: [p.steps!, 0, 0], floats: [p.steps! / 2], aux: new Float32Array(1) };\n case \"grey-ramp\": return { ints: [1024, 0, 0], floats: [512], aux: new Float32Array(1) };\n case \"checkerboard\": return { ints: [0, 0, 0], floats: [p.squaresAcross! / 2, aspect], aux: new Float32Array(1) };\n case \"point-grid\": {\n const columns = p.columns!, rows = p.rows!, centers = calculatePointGridCenters({ columns, rows, aspect });\n return { ints: [columns, rows, 0], floats: [columns / 2, aspect, rows / (2 * aspect), p.radius! * p.radius!],\n aux: Float32Array.from(centers.flatMap(c => [c.u, c.v])) };\n }\n case \"patches\": {\n const columns = p.columns!, rows = p.rows!, count = (chart.parameters.patchIds as readonly string[]).length;\n return { ints: [columns, rows, count], floats: [columns / 2, aspect, rows / (2 * aspect), p.gapFraction! / 2, 1 - p.gapFraction! / 2],\n aux: new Float32Array(1) };\n }\n }\n}\n\n/** Per-material values in float64, with the reference's operations; a material whose spectrum fails is NaN (recomputed on the host). */\nfunction materialTable(plan: ChartRadianceBatchPlan): Float32Array<ArrayBuffer> {\n const materials = plan.chart.materials.length, nm = plan.wavelengthsNanometers, stride = plan.mode === \"radiance\" ? nm.length : plan.columns;\n const table = new Float32Array(materials * stride);\n for (let m = 0; m < materials; m++) {\n for (let c = 0; c < stride; c++) {\n let value: number;\n try {\n if (plan.mode === \"radiance\") value = plan.materialRadiance(m, nm[c]!);\n else {\n value = 0;\n const row = plan.channelWeights![c]!;\n for (let j = 0; j < nm.length; j++) value += row[j]! * plan.materialRadiance(m, nm[j]!);\n }\n } catch {\n value = Number.NaN;\n }\n if (Math.abs(value) > FLOAT32_SAFE_MAGNITUDE) throw new ImageKernelExecutionError(\"unsupported-float32-domain\", \"Chart values exceed the float32 domain.\");\n table[m * stride + c] = value;\n }\n }\n return table;\n}\n\nexport async function evaluateChartRadianceOnGpu(runtime: WebGpuRuntime, bandBytes: number, input: ChartRadianceBatchInput, abort: AbortController,\n yieldControl: YieldControl, pipelines: PipelineSource): Promise<ChartRadianceResult> {\n const plan = calculateChartRadianceBatchPlan(input), points = input.points.slice(), indices = input.wavelengthIndices?.slice();\n for (let i = 0; i < points.length; i++) {\n if (Math.abs(points[i]!) > CHART_GPU_MAXIMUM_COORDINATE) throw new ImageKernelExecutionError(\"unsupported-float32-domain\", \"Chart points beyond 2^20 frame units are outside the float32 domain.\");\n }\n const { ints, floats, aux } = chartGpuConstants(plan), table = materialTable(plan), radianceMode = plan.mode === \"radiance\";\n const columns = plan.columns, stride = radianceMode ? plan.wavelengthsNanometers.length : columns, count = plan.queryCount;\n const bytesPerQuery = 8 + 4 * columns + 4 + 4;\n const rows = Math.max(1, Math.floor(bandBytes / bytesPerQuery));\n if (Math.max(table.byteLength, aux.byteLength, Math.min(rows, count) * 4 * columns) > runtime.maximumStorageBindingBytes) {\n throw new ImageKernelExecutionError(\"insufficient-limits\", \"Chart tables or bands exceed the device's storage binding limit.\");\n }\n const params = new ArrayBuffer(64), words = new Uint32Array(params), f = new Float32Array(params);\n words[1] = stride; words[2] = CHART_PRESET_CODE[plan.chart.preset]; words[3] = ints[0]; words[4] = ints[1]; words[5] = ints[2]; words[6] = radianceMode ? 1 : 0;\n f.set(floats, 8);\n const pipeline = await pipelines(\"photivra-chart-radiance\", CHART_RADIANCE_WGSL);\n const values = new Float32Array(count * columns), recomputed: number[] = [];\n const scope = new GpuResourceScope(runtime);\n try {\n const tableBuffer = scope.upload(\"photivra-chart-table\", table, BUFFER_USAGE.STORAGE);\n const auxBuffer = scope.upload(\"photivra-chart-aux\", aux, BUFFER_USAGE.STORAGE);\n const gate = createHostYieldGate();\n for (let first = 0; first < count; first += rows) {\n checkAbort(abort.signal);\n const n = Math.min(rows, count - first);\n words[0] = n;\n const band = new GpuResourceScope(runtime);\n try {\n const pointBuffer = band.upload(\"photivra-chart-points\", new Float32Array(points.subarray(2 * first, 2 * (first + n))), BUFFER_USAGE.STORAGE);\n const selectors = band.upload(\"photivra-chart-selectors\", indices ? Uint32Array.from(indices.subarray(first, first + n)) : new Uint32Array(1), BUFFER_USAGE.STORAGE);\n const out = band.buffer(\"photivra-chart-values\", n * 4 * columns, BUFFER_USAGE.STORAGE | BUFFER_USAGE.COPY_SRC);\n const flagBuffer = band.buffer(\"photivra-chart-flags\", n * 4, BUFFER_USAGE.STORAGE | BUFFER_USAGE.COPY_SRC);\n const uniform = band.upload(\"photivra-chart-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: pointBuffer } }, { binding: 2, resource: { buffer: tableBuffer } },\n { binding: 3, resource: { buffer: auxBuffer } }, { binding: 4, resource: { buffer: selectors } }, { binding: 5, resource: { buffer: out } },\n { binding: 6, resource: { buffer: flagBuffer } }] });\n const [valueData, flagData] = await runComputePass(runtime, band, pipeline, bindGroup, linearDispatch(n, CHART_WORKGROUP_SIZE, runtime.maximumWorkgroupsPerDimension),\n [{ buffer: out, bytes: n * 4 * columns }, { buffer: flagBuffer, bytes: n * 4 }], abort.signal);\n values.set(new Float32Array(valueData!, 0, n * columns), first * columns);\n const bandFlags = new Uint32Array(flagData!, 0, n);\n for (let i = 0; i < n; i++) {\n let recompute = bandFlags[i] !== 0;\n for (let c = 0; c < columns && !recompute; c++) if (!Number.isFinite(values[(first + i) * columns + c]!)) recompute = true;\n if (recompute) recomputed.push(first + i);\n }\n } finally {\n band.release();\n }\n if (yieldControl && gate.due()) { await yieldControl(abort.signal); gate.restart(); }\n }\n } finally {\n scope.release();\n }\n checkAbort(abort.signal);\n // Flagged points (and any whose material spectrum failed): the reference's own value, rounded once to float32.\n for (const q of recomputed) for (let c = 0; c < columns; c++) values[q * columns + c] = plan.queryValue(points, indices, q, c);\n const execution = webGpuExecution({ kind: \"relative-to-reference\", relative: 2 ** -24, absolute: 2 ** -126 }, 0);\n return { plan, values, columns, execution, hostRecomputedQueryIndices: Uint32Array.from(recomputed) };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"chart-radiance-gpu.js","sourceRoot":"","sources":["../../src/gpu/chart-radiance-gpu.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Host side of the `webgpu-f32` chart-radiance stage (#277): per-material value tables in float64 (the\n * reference's own operations), preset constants, banded dispatch, readback, and host recomputation of\n * flagged points with the reference. The float64 reference is `calculateChartRadianceBatch`\n * (facade/chart-radiance-batch.ts). Internal; the public entry point is the image-kernel accelerator.\n */\nimport { createHostYieldGate } from \"../capture/host-yield-cadence.js\";\nimport { calculateChartRadianceBatchPlan, type ChartRadianceBatchInput, type ChartRadianceBatchPlan } from \"../facade/chart-radiance-batch.js\";\nimport { calculatePointGridCenters } from \"../facade/chart-scenes.js\";\nimport { ImageKernelExecutionError, webGpuExecution, type ImageKernelExecution } from \"./image-kernel-execution.js\";\nimport type { ChartRadianceResult } from \"./image-kernel-accelerator.js\";\nimport { BUFFER_USAGE, GpuResourceScope, abortedError, linearDispatch, runComputePass, type WebGpuRuntime } from \"./webgpu-runtime.js\";\nimport { CHART_PRESET_CODE, CHART_RADIANCE_WGSL, CHART_WORKGROUP_SIZE } from \"./wgsl-chart-kernel.js\";\n\ntype PipelineSource = (label: string, code: string) => Promise<GPUComputePipeline>;\ntype YieldControl = ((signal: AbortSignal) => Promise<void>) | undefined;\n\n/** Frame-unit magnitude limit for GPU points. */\nexport const CHART_GPU_MAXIMUM_COORDINATE = 2 ** 20;\nconst FLOAT32_SAFE_MAGNITUDE = 2 ** 120;\n\n\nfunction checkAbort(signal: AbortSignal): void {\n if (signal.aborted) throw abortedError();\n}\n\nexport async function evaluateChartRadianceOnCpu(input: ChartRadianceBatchInput, abort: AbortController, yieldControl: YieldControl,\n execution: ImageKernelExecution): Promise<ChartRadianceResult> {\n const plan = calculateChartRadianceBatchPlan(input), points = input.points.slice(), indices = input.wavelengthIndices?.slice();\n const values = new Float64Array(plan.queryCount * plan.columns), gate = createHostYieldGate();\n for (let q = 0; q < plan.queryCount; q++) {\n for (let c = 0; c < plan.columns; c++) values[q * plan.columns + c] = plan.queryValue(points, indices, q, c);\n if ((q & 0xffff) === 0xffff) {\n checkAbort(abort.signal);\n if (yieldControl && gate.due()) { await yieldControl(abort.signal); gate.restart(); }\n }\n }\n checkAbort(abort.signal);\n return { plan, values, columns: plan.columns, execution, hostRecomputedQueryIndices: new Uint32Array(0) };\n}\n\n/**\n * The preset code of a chart the WGSL kernel classifies, or undefined. The kernel covers the eight 2.0 presets\n * (a Siemens star only with the bar profile). The 2.3 elements and composites run on `cpu-reference`: their\n * continuous profiles need WGSL sin/cos/atan2 whose accuracy bounds would flag a large share of points for host\n * recomputation, and dead leaves, bar groups and composites need per-element tables not yet written or measured\n * on a device. @internal\n */\nexport function chartGpuPresetCode(plan: ChartRadianceBatchPlan): number | undefined {\n const preset = plan.chart.preset;\n if (!Object.prototype.hasOwnProperty.call(CHART_PRESET_CODE, preset) || plan.chart.parameters.profile === \"sine\") return undefined;\n return CHART_PRESET_CODE[preset as keyof typeof CHART_PRESET_CODE];\n}\n\n/** Preset constants (uniform words 3–5 and floats 8–15) and the auxiliary table. @internal */\nexport function chartGpuConstants(plan: ChartRadianceBatchPlan): { ints: [number, number, number]; floats: number[]; aux: Float32Array<ArrayBuffer> } {\n const chart = plan.chart, p = chart.parameters as Record<string, number>, aspect = chart.aspect;\n switch (chart.preset) {\n case \"uniform\": return { ints: [0, 0, 0], floats: [], aux: new Float32Array(1) };\n case \"slanted-edge\": {\n // The same float64 constants as resolveChartScene.\n const t = p.angleDegrees! * Math.PI / 180;\n return { ints: [0, 0, 0], floats: [Math.cos(t), Math.sin(t)], aux: new Float32Array(1) };\n }\n case \"siemens-star\": {\n const cycles = p.cycles!, r = p.radiusFraction! * aspect, aux = new Float32Array(2 * (2 * cycles + 1));\n // Sector boundaries: phase·2·cycles = k ⇔ θ = π(k/cycles − 1).\n for (let k = 0; k <= 2 * cycles; k++) { const b = Math.PI * (k / cycles - 1); aux[2 * k] = Math.cos(b); aux[2 * k + 1] = Math.sin(b); }\n return { ints: [cycles, 0, 0], floats: [r * r], aux };\n }\n case \"step-wedge\": return { ints: [p.steps!, 0, 0], floats: [p.steps! / 2], aux: new Float32Array(1) };\n case \"grey-ramp\": return { ints: [1024, 0, 0], floats: [512], aux: new Float32Array(1) };\n case \"checkerboard\": return { ints: [0, 0, 0], floats: [p.squaresAcross! / 2, aspect], aux: new Float32Array(1) };\n case \"point-grid\": {\n const columns = p.columns!, rows = p.rows!, centers = calculatePointGridCenters({ columns, rows, aspect });\n return { ints: [columns, rows, 0], floats: [columns / 2, aspect, rows / (2 * aspect), p.radius! * p.radius!],\n aux: Float32Array.from(centers.flatMap(c => [c.u, c.v])) };\n }\n case \"patches\": {\n const columns = p.columns!, rows = p.rows!, count = (chart.parameters.patchIds as readonly string[]).length;\n return { ints: [columns, rows, count], floats: [columns / 2, aspect, rows / (2 * aspect), p.gapFraction! / 2, 1 - p.gapFraction! / 2],\n aux: new Float32Array(1) };\n }\n default: throw new ImageKernelExecutionError(\"unsupported-on-backend\", \"webgpu-f32 classifies the eight 2.0 chart presets; use cpu-reference for \" + chart.preset + \".\");\n }\n}\n\n/** Per-material values in float64, with the reference's operations; a material whose spectrum fails is NaN (recomputed on the host). */\nfunction materialTable(plan: ChartRadianceBatchPlan): Float32Array<ArrayBuffer> {\n const materials = plan.chart.materials.length, nm = plan.wavelengthsNanometers, stride = plan.mode === \"radiance\" ? nm.length : plan.columns;\n const table = new Float32Array(materials * stride);\n for (let m = 0; m < materials; m++) {\n for (let c = 0; c < stride; c++) {\n let value: number;\n try {\n if (plan.mode === \"radiance\") value = plan.materialRadiance(m, nm[c]!);\n else {\n value = 0;\n const row = plan.channelWeights![c]!;\n for (let j = 0; j < nm.length; j++) value += row[j]! * plan.materialRadiance(m, nm[j]!);\n }\n } catch {\n value = Number.NaN;\n }\n if (Math.abs(value) > FLOAT32_SAFE_MAGNITUDE) throw new ImageKernelExecutionError(\"unsupported-float32-domain\", \"Chart values exceed the float32 domain.\");\n table[m * stride + c] = value;\n }\n }\n return table;\n}\n\nexport async function evaluateChartRadianceOnGpu(runtime: WebGpuRuntime, bandBytes: number, input: ChartRadianceBatchInput, abort: AbortController,\n yieldControl: YieldControl, pipelines: PipelineSource): Promise<ChartRadianceResult> {\n const plan = calculateChartRadianceBatchPlan(input), points = input.points.slice(), indices = input.wavelengthIndices?.slice();\n const presetCode = chartGpuPresetCode(plan);\n if (presetCode === undefined) {\n throw new ImageKernelExecutionError(\"unsupported-on-backend\", \"webgpu-f32 classifies the eight 2.0 chart presets (Siemens star with the bar profile); use cpu-reference for \" +\n plan.chart.preset + (plan.chart.parameters.profile === \"sine\" ? \" (sine profile)\" : \"\") + \".\");\n }\n for (let i = 0; i < points.length; i++) {\n if (Math.abs(points[i]!) > CHART_GPU_MAXIMUM_COORDINATE) throw new ImageKernelExecutionError(\"unsupported-float32-domain\", \"Chart points beyond 2^20 frame units are outside the float32 domain.\");\n }\n const { ints, floats, aux } = chartGpuConstants(plan), table = materialTable(plan), radianceMode = plan.mode === \"radiance\";\n const columns = plan.columns, stride = radianceMode ? plan.wavelengthsNanometers.length : columns, count = plan.queryCount;\n const bytesPerQuery = 8 + 4 * columns + 4 + 4;\n const rows = Math.max(1, Math.floor(bandBytes / bytesPerQuery));\n if (Math.max(table.byteLength, aux.byteLength, Math.min(rows, count) * 4 * columns) > runtime.maximumStorageBindingBytes) {\n throw new ImageKernelExecutionError(\"insufficient-limits\", \"Chart tables or bands exceed the device's storage binding limit.\");\n }\n const params = new ArrayBuffer(64), words = new Uint32Array(params), f = new Float32Array(params);\n words[1] = stride; words[2] = presetCode; words[3] = ints[0]; words[4] = ints[1]; words[5] = ints[2]; words[6] = radianceMode ? 1 : 0;\n f.set(floats, 8);\n const pipeline = await pipelines(\"photivra-chart-radiance\", CHART_RADIANCE_WGSL);\n const values = new Float32Array(count * columns), recomputed: number[] = [];\n const scope = new GpuResourceScope(runtime);\n try {\n const tableBuffer = scope.upload(\"photivra-chart-table\", table, BUFFER_USAGE.STORAGE);\n const auxBuffer = scope.upload(\"photivra-chart-aux\", aux, BUFFER_USAGE.STORAGE);\n const gate = createHostYieldGate();\n for (let first = 0; first < count; first += rows) {\n checkAbort(abort.signal);\n const n = Math.min(rows, count - first);\n words[0] = n;\n const band = new GpuResourceScope(runtime);\n try {\n const pointBuffer = band.upload(\"photivra-chart-points\", new Float32Array(points.subarray(2 * first, 2 * (first + n))), BUFFER_USAGE.STORAGE);\n const selectors = band.upload(\"photivra-chart-selectors\", indices ? Uint32Array.from(indices.subarray(first, first + n)) : new Uint32Array(1), BUFFER_USAGE.STORAGE);\n const out = band.buffer(\"photivra-chart-values\", n * 4 * columns, BUFFER_USAGE.STORAGE | BUFFER_USAGE.COPY_SRC);\n const flagBuffer = band.buffer(\"photivra-chart-flags\", n * 4, BUFFER_USAGE.STORAGE | BUFFER_USAGE.COPY_SRC);\n const uniform = band.upload(\"photivra-chart-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: pointBuffer } }, { binding: 2, resource: { buffer: tableBuffer } },\n { binding: 3, resource: { buffer: auxBuffer } }, { binding: 4, resource: { buffer: selectors } }, { binding: 5, resource: { buffer: out } },\n { binding: 6, resource: { buffer: flagBuffer } }] });\n const [valueData, flagData] = await runComputePass(runtime, band, pipeline, bindGroup, linearDispatch(n, CHART_WORKGROUP_SIZE, runtime.maximumWorkgroupsPerDimension),\n [{ buffer: out, bytes: n * 4 * columns }, { buffer: flagBuffer, bytes: n * 4 }], abort.signal);\n values.set(new Float32Array(valueData!, 0, n * columns), first * columns);\n const bandFlags = new Uint32Array(flagData!, 0, n);\n for (let i = 0; i < n; i++) {\n let recompute = bandFlags[i] !== 0;\n for (let c = 0; c < columns && !recompute; c++) if (!Number.isFinite(values[(first + i) * columns + c]!)) recompute = true;\n if (recompute) recomputed.push(first + i);\n }\n } finally {\n band.release();\n }\n if (yieldControl && gate.due()) { await yieldControl(abort.signal); gate.restart(); }\n }\n } finally {\n scope.release();\n }\n checkAbort(abort.signal);\n // Flagged points (and any whose material spectrum failed): the reference's own value, rounded once to float32.\n for (const q of recomputed) for (let c = 0; c < columns; c++) values[q * columns + c] = plan.queryValue(points, indices, q, c);\n const execution = webGpuExecution({ kind: \"relative-to-reference\", relative: 2 ** -24, absolute: 2 ** -126 }, 0);\n return { plan, values, columns, execution, hostRecomputedQueryIndices: Uint32Array.from(recomputed) };\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -197,9 +197,11 @@ export { createFocusStackTask, type FocusStackInput, type FocusStackOutput } fro
|
|
|
197
197
|
export { createPanoramaTask, type PanoramaFrame, type PanoramaCanvas, type PanoramaInput, type PanoramaOutput } from "./processing/panorama.js";
|
|
198
198
|
export { SYNTHETIC_FILM_GRAIN_STREAM_ID, createBilateralFilterTask, createNonLocalMeansTask, createUnsharpMaskTask, createSyntheticFilmGrainTask, type ProcessedRgbImage, type BilateralFilterInput, type NonLocalMeansInput, type UnsharpMaskInput, type SyntheticFilmGrainInput, type SyntheticFilmGrainOutput } from "./processing/denoise.js";
|
|
199
199
|
export { calculateSensorApertureRays, type CalculateSensorApertureRaysInput, type IdealCircularPupil, type SensorApertureRay, type SensorApertureRays } from "./optics/sensor-aperture-rays.js";
|
|
200
|
-
export { SIMULATE_CAPTURE_FACADE_VERSION, SIMULATE_CAPTURE_DEFAULT_ILLUMINANCE_LUX, SIMULATE_CAPTURE_COST_OPTIONS, simulateCapture, type SimulateCaptureOptions, type SimulateCaptureResult, type SimulateCaptureAssumption, type SimulateCaptureProgress, type SimulateCaptureExposureMode, type SimulateCaptureOutputFormat, type SimulateCaptureWhiteBalance, type SimulateCaptureColorEncoding, type SimulateCaptureDemosaic, type SimulateCaptureBorderHandling, type SimulateCaptureLensDistortion, type SimulateCaptureMotion, type SimulateCaptureSensorAntiAliasing, type SimulateCaptureCostOption } from "./facade/simulate-capture.js";
|
|
201
|
-
export {
|
|
202
|
-
export {
|
|
200
|
+
export { SIMULATE_CAPTURE_FACADE_VERSION, SIMULATE_CAPTURE_DEFAULT_ILLUMINANCE_LUX, SIMULATE_CAPTURE_COST_OPTIONS, simulateCapture, type SimulateCaptureOptions, type SimulateCaptureResult, type SimulateCaptureAssumption, type SimulateCaptureProgress, type SimulateCaptureExposureMode, type SimulateCaptureOutputFormat, type SimulateCaptureWhiteBalance, type SimulateCaptureColorEncoding, type SimulateCaptureDemosaic, type SimulateCaptureBorderHandling, type SimulateCaptureLensDistortion, type SimulateCaptureMotion, type SimulateCaptureSensorAntiAliasing, type SimulateCaptureCostOption, type SimulateCapturePixelAperture, SIMULATE_CAPTURE_BOX_APERTURE_DEFAULT_SAMPLES, simulateIdealReference, type IdealReferenceResult } from "./facade/simulate-capture.js";
|
|
201
|
+
export { GENERIC_PRIME_EQUIVALENT_FOCAL_LENGTHS_MM, GENERIC_PRIME_THIRD_STOP_F_NUMBERS, GENERIC_PRIME_MINIMUM_FOCUS, resolveGenericPrimeLens, calculateGenericPrimeMinimumFocusDistanceM, type GenericPrimeLens, type GenericPrimeEquivalentFocalLengthMm } from "./equipment/generic-prime-lenses.js";
|
|
202
|
+
export { calculateSubjectDistanceForFraming, type CalculateSubjectDistanceForFramingInput, type SubjectFraming, type SubjectFramingFit } from "./facade/subject-framing.js";
|
|
203
|
+
export { CHART_SCENE_PRESETS, CHART_SCENE_DEFAULTS, CHART_SPECTRAL_RANGE_NANOMETERS, resolveChartScene, calculateStepWedgeReflectances, calculatePointGridCenters, type ChartScene, type ChartScenePresetId, type ChartReflectance, type ResolvedChartScene, type UniformChartScene, type SlantedEdgeChartScene, type SiemensStarChartScene, type StepWedgeChartScene, type GreyRampChartScene, type CheckerboardChartScene, type PointGridChartScene, type PatchChartScene, CHART_CONTINUOUS_LEVELS, calculateBarGroupTargets, calculateSlantedSquareEdges, type DeadLeavesChartScene, type BarGroupsChartScene, type HyperbolicWedgeChartScene, type ZonePlateChartScene, type SlantedSquaresChartScene, type LineGridChartScene, type FiducialChartScene, type CompositeChartScene, type CompositeChartElement, type ChartElementScene, type ChartRectangle, type ChartBarGroupTarget, type ChartSlantedSquare } from "./facade/chart-scenes.js";
|
|
204
|
+
export { PHOTOPIC_MAXIMUM_LUMINOUS_EFFICACY_LM_PER_W, resolveCaptureIlluminant, createPlanarSceneRadianceProvider, CHART_SIZE_DEFAULT_SURROUND_REFLECTANCE, type ChartSizeOption, type CaptureIlluminant, type ResolvedCaptureIlluminant, type CallerReflectanceScene, type CallerRadianceScene, type ScenePlanePoint, type PlanarSceneRadianceProvider } from "./facade/scene-radiance.js";
|
|
203
205
|
export { CHART_RADIANCE_BATCH_SCHEMA_VERSION, CHART_RADIANCE_BATCH_LIMITS, calculateChartRadianceBatchPlan, calculateChartRadianceBatch, mapEnvironmentDirectionsToChartPoints, type ChartRadianceBatchInput, type ChartRadianceBatchPlan } from "./facade/chart-radiance-batch.js";
|
|
204
206
|
export { EXPORT_JPEG_ENCODER_ID } from "./capture/export-jpeg.js";
|
|
205
207
|
export { DNG_IMPORT_SCHEMA_VERSION, DNG_IMPORT_LIMITS, parseDngRawImage } from "./capture/dng-import.js";
|
package/dist/index.js
CHANGED
|
@@ -176,9 +176,11 @@ export { createFocusStackTask } from "./processing/focus-stacking.js";
|
|
|
176
176
|
export { createPanoramaTask } from "./processing/panorama.js";
|
|
177
177
|
export { SYNTHETIC_FILM_GRAIN_STREAM_ID, createBilateralFilterTask, createNonLocalMeansTask, createUnsharpMaskTask, createSyntheticFilmGrainTask } from "./processing/denoise.js";
|
|
178
178
|
export { calculateSensorApertureRays } from "./optics/sensor-aperture-rays.js";
|
|
179
|
-
export { SIMULATE_CAPTURE_FACADE_VERSION, SIMULATE_CAPTURE_DEFAULT_ILLUMINANCE_LUX, SIMULATE_CAPTURE_COST_OPTIONS, simulateCapture } from "./facade/simulate-capture.js";
|
|
180
|
-
export {
|
|
181
|
-
export {
|
|
179
|
+
export { SIMULATE_CAPTURE_FACADE_VERSION, SIMULATE_CAPTURE_DEFAULT_ILLUMINANCE_LUX, SIMULATE_CAPTURE_COST_OPTIONS, simulateCapture, SIMULATE_CAPTURE_BOX_APERTURE_DEFAULT_SAMPLES, simulateIdealReference } from "./facade/simulate-capture.js";
|
|
180
|
+
export { GENERIC_PRIME_EQUIVALENT_FOCAL_LENGTHS_MM, GENERIC_PRIME_THIRD_STOP_F_NUMBERS, GENERIC_PRIME_MINIMUM_FOCUS, resolveGenericPrimeLens, calculateGenericPrimeMinimumFocusDistanceM } from "./equipment/generic-prime-lenses.js";
|
|
181
|
+
export { calculateSubjectDistanceForFraming } from "./facade/subject-framing.js";
|
|
182
|
+
export { CHART_SCENE_PRESETS, CHART_SCENE_DEFAULTS, CHART_SPECTRAL_RANGE_NANOMETERS, resolveChartScene, calculateStepWedgeReflectances, calculatePointGridCenters, CHART_CONTINUOUS_LEVELS, calculateBarGroupTargets, calculateSlantedSquareEdges } from "./facade/chart-scenes.js";
|
|
183
|
+
export { PHOTOPIC_MAXIMUM_LUMINOUS_EFFICACY_LM_PER_W, resolveCaptureIlluminant, createPlanarSceneRadianceProvider, CHART_SIZE_DEFAULT_SURROUND_REFLECTANCE } from "./facade/scene-radiance.js";
|
|
182
184
|
export { CHART_RADIANCE_BATCH_SCHEMA_VERSION, CHART_RADIANCE_BATCH_LIMITS, calculateChartRadianceBatchPlan, calculateChartRadianceBatch, mapEnvironmentDirectionsToChartPoints } from "./facade/chart-radiance-batch.js";
|
|
183
185
|
export { EXPORT_JPEG_ENCODER_ID } from "./capture/export-jpeg.js";
|
|
184
186
|
export { DNG_IMPORT_SCHEMA_VERSION, DNG_IMPORT_LIMITS, parseDngRawImage } from "./capture/dng-import.js";
|