@photivra/engine 2.21.0 → 2.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +150 -1
- package/CITATION.cff +1 -1
- package/README.md +6 -6
- package/SECURITY.md +1 -1
- package/THIRD_PARTY.md +11 -0
- package/dist/capture/c2pa-embed.d.ts +116 -0
- package/dist/capture/c2pa-embed.js +493 -0
- package/dist/capture/c2pa-embed.js.map +1 -0
- package/dist/capture/dng-import.d.ts +73 -8
- package/dist/capture/dng-import.js +315 -80
- package/dist/capture/dng-import.js.map +1 -1
- package/dist/capture/dng-opcodes.d.ts +96 -0
- package/dist/capture/dng-opcodes.js +391 -0
- package/dist/capture/dng-opcodes.js.map +1 -0
- package/dist/capture/dng-profile-maps.d.ts +99 -0
- package/dist/capture/dng-profile-maps.js +381 -0
- package/dist/capture/dng-profile-maps.js.map +1 -0
- package/dist/capture/dng-stage-image.d.ts +23 -0
- package/dist/capture/dng-stage-image.js +65 -0
- package/dist/capture/dng-stage-image.js.map +1 -0
- package/dist/capture/jpeg-xl-tiles.d.ts +22 -0
- package/dist/capture/jpeg-xl-tiles.js +151 -0
- package/dist/capture/jpeg-xl-tiles.js.map +1 -0
- package/dist/capture/lossy-jpeg.d.ts +17 -0
- package/dist/capture/lossy-jpeg.js +369 -0
- package/dist/capture/lossy-jpeg.js.map +1 -0
- package/dist/capture/native-raw-development.d.ts +2 -1
- package/dist/capture/native-raw-development.js.map +1 -1
- package/dist/color/neighbor-highlight-reconstruction.d.ts +76 -0
- package/dist/color/neighbor-highlight-reconstruction.js +257 -0
- package/dist/color/neighbor-highlight-reconstruction.js.map +1 -0
- package/dist/color/sensor-color-development.d.ts +5 -0
- package/dist/color/sensor-color-development.js +7 -1
- package/dist/color/sensor-color-development.js.map +1 -1
- package/dist/color/spectral-spikiness.d.ts +11 -0
- package/dist/color/spectral-spikiness.js +23 -0
- package/dist/color/spectral-spikiness.js.map +1 -0
- package/dist/core/execution-error.d.ts +21 -0
- package/dist/core/execution-error.js +12 -0
- package/dist/core/execution-error.js.map +1 -0
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/dist/core/version.js.map +1 -1
- package/dist/facade/catalogue-lens-signal.d.ts +26 -1
- package/dist/facade/catalogue-lens-signal.js +25 -7
- package/dist/facade/catalogue-lens-signal.js.map +1 -1
- package/dist/facade/diffraction-provider.d.ts +1 -1
- package/dist/facade/diffraction-provider.js +4 -4
- package/dist/facade/diffraction-provider.js.map +1 -1
- package/dist/facade/display-view-gpu-session.js +38 -6
- package/dist/facade/display-view-gpu-session.js.map +1 -1
- package/dist/facade/display-view-gpu.d.ts +13 -5
- package/dist/facade/display-view-gpu.js.map +1 -1
- package/dist/facade/display-view-normal.d.ts +15 -0
- package/dist/facade/display-view-normal.js +44 -0
- package/dist/facade/display-view-normal.js.map +1 -0
- package/dist/facade/display-view-rendering.d.ts +102 -0
- package/dist/facade/display-view-rendering.js +633 -0
- package/dist/facade/display-view-rendering.js.map +1 -0
- package/dist/facade/display-view.d.ts +37 -65
- package/dist/facade/display-view.js +147 -476
- package/dist/facade/display-view.js.map +1 -1
- package/dist/facade/expected-signal-setup.js +2 -2
- package/dist/facade/expected-signal-setup.js.map +1 -1
- package/dist/facade/fast-methods.d.ts +1 -1
- package/dist/facade/fast-methods.js +37 -8
- package/dist/facade/fast-methods.js.map +1 -1
- package/dist/facade/generic-lens-capture.d.ts +1 -1
- package/dist/facade/generic-lens-capture.js +1 -1
- package/dist/facade/generic-lens-capture.js.map +1 -1
- package/dist/facade/image-plane.js +41 -10
- package/dist/facade/image-plane.js.map +1 -1
- package/dist/facade/on-demand-kits.d.ts +14 -0
- package/dist/facade/on-demand-kits.js +36 -0
- package/dist/facade/on-demand-kits.js.map +1 -0
- package/dist/facade/opt-in-kit.d.ts +9 -0
- package/dist/facade/opt-in-kit.js +11 -0
- package/dist/facade/opt-in-kit.js.map +1 -0
- package/dist/facade/quality-kit.d.ts +21 -0
- package/dist/facade/quality-kit.js +23 -0
- package/dist/facade/quality-kit.js.map +1 -0
- package/dist/facade/quality-paths.d.ts +22 -0
- package/dist/facade/quality-paths.js +44 -0
- package/dist/facade/quality-paths.js.map +1 -0
- package/dist/facade/scene-radiance.d.ts +18 -2
- package/dist/facade/scene-radiance.js +6 -4
- package/dist/facade/scene-radiance.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +32 -13
- package/dist/facade/simulate-capture.js +162 -69
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/facade/simulate-display-view.d.ts +10 -12
- package/dist/facade/simulate-display-view.js +57 -48
- package/dist/facade/simulate-display-view.js.map +1 -1
- package/dist/gpu/display-view-gpu-renderer.d.ts +43 -0
- package/dist/gpu/display-view-gpu-renderer.js +134 -0
- package/dist/gpu/display-view-gpu-renderer.js.map +1 -0
- package/dist/gpu/display-view-image-material-module.d.ts +3 -2
- package/dist/gpu/display-view-image-material-module.js +25 -3
- package/dist/gpu/display-view-image-material-module.js.map +1 -1
- package/dist/gpu/display-view-image-quality.d.ts +43 -1
- package/dist/gpu/display-view-image-quality.js +256 -11
- package/dist/gpu/display-view-image-quality.js.map +1 -1
- package/dist/gpu/display-view-quality-gpu.d.ts +13 -64
- package/dist/gpu/display-view-quality-gpu.js +55 -240
- package/dist/gpu/display-view-quality-gpu.js.map +1 -1
- package/dist/gpu/display-view-speed-gpu.d.ts +16 -16
- package/dist/gpu/display-view-speed-gpu.js +62 -19
- package/dist/gpu/display-view-speed-gpu.js.map +1 -1
- package/dist/gpu/image-kernel-accelerator.js +3 -0
- package/dist/gpu/image-kernel-accelerator.js.map +1 -1
- package/dist/gpu/image-kernel-execution.d.ts +2 -13
- package/dist/gpu/image-kernel-execution.js +2 -10
- package/dist/gpu/image-kernel-execution.js.map +1 -1
- package/dist/gpu/wgsl-display-view-coupled-stub.d.ts +13 -0
- package/dist/gpu/wgsl-display-view-coupled-stub.js +29 -0
- package/dist/gpu/wgsl-display-view-coupled-stub.js.map +1 -0
- package/dist/gpu/wgsl-display-view-coupled.d.ts +91 -0
- package/dist/gpu/wgsl-display-view-coupled.js +365 -0
- package/dist/gpu/wgsl-display-view-coupled.js.map +1 -0
- package/dist/gpu/wgsl-display-view-neighbors.d.ts +46 -0
- package/dist/gpu/wgsl-display-view-neighbors.js +114 -0
- package/dist/gpu/wgsl-display-view-neighbors.js.map +1 -0
- package/dist/gpu/wgsl-display-view-quality-kernel.d.ts +6 -9
- package/dist/gpu/wgsl-display-view-quality-kernel.js +113 -113
- package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -1
- package/dist/gpu/wgsl-display-view-speed-kernel.d.ts +1 -41
- package/dist/gpu/wgsl-display-view-speed-kernel.js +73 -10
- package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -1
- package/dist/index.d.ts +11 -3
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/output/camera-channel-response.d.ts +50 -0
- package/dist/output/camera-channel-response.js +69 -0
- package/dist/output/camera-channel-response.js.map +1 -0
- package/dist/output/native-capture-sdr.js +5 -2
- package/dist/output/native-capture-sdr.js.map +1 -1
- package/dist/output/sdr-rendering.d.ts +18 -1
- package/dist/output/sdr-rendering.js +39 -2
- package/dist/output/sdr-rendering.js.map +1 -1
- package/dist/sensor/native-sensor-report.d.ts +10 -0
- package/dist/sensor/native-sensor-report.js +16 -0
- package/dist/sensor/native-sensor-report.js.map +1 -0
- package/dist/sensor/sensor-characteristics.d.ts +81 -13
- package/dist/sensor/sensor-characteristics.js +10 -6
- package/dist/sensor/sensor-characteristics.js.map +1 -1
- package/docs/API_REFERENCE.md +117 -4
- package/docs/QUICK_START.md +37 -8
- package/docs/USAGE.md +105 -22
- package/docs/api/capture-c2pa-embed.md +177 -0
- package/docs/api/capture-dng-import.md +86 -10
- package/docs/api/capture-dng-opcodes.md +93 -0
- package/docs/api/capture-dng-profile-maps.md +141 -0
- package/docs/api/capture-dng-stage-image.md +43 -0
- package/docs/api/capture-jpeg-xl-tiles.md +33 -0
- package/docs/api/capture-lossy-jpeg.md +41 -0
- package/docs/api/capture-native-raw-development.md +2 -1
- package/docs/api/core-execution-error.md +43 -0
- package/docs/api/core-version.md +1 -1
- package/docs/api/exports.json +255 -5
- package/docs/api/facade-display-view-gpu.md +5 -2
- package/docs/api/facade-display-view.md +11 -15
- package/docs/api/facade-fast-methods.md +38 -9
- package/docs/api/facade-quality-paths.md +24 -0
- package/docs/api/facade-scene-radiance.md +1 -1
- package/docs/api/facade-simulate-capture.md +24 -7
- package/docs/api/facade-simulate-display-view.md +10 -12
- package/docs/api/gpu-image-kernel-execution.md +0 -36
- package/docs/api/output-camera-channel-response.md +55 -0
- package/docs/api/output-sdr-rendering.md +6 -1
- package/docs/api/sensor-sensor-characteristics.md +54 -2
- package/llms.txt +1 -0
- package/package.json +6 -5
|
@@ -1,18 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* Host side of the display view's Speed path on the GPU (#478): the support check, the float64 tables (site table,
|
|
3
|
-
* overlaps over the scale, axis sums over the squared scale, 1/Σw²), banded dispatch of
|
|
4
|
-
* `DISPLAY_VIEW_SPEED_KERNEL_WGSL`, and the finishing the CPU reference does after its per-sample loop: the output
|
|
5
|
-
* quantization term, the seeded noise draw, the Cholesky factor, the clipped-normal centre, the sRGB encode and the
|
|
6
|
-
* rounding, all with the reference's own float64 functions. So the noise draw is bit-identical to the CPU's, and only
|
|
7
|
-
* the expected value and the covariance carry the float32 bound.
|
|
8
|
-
*
|
|
9
|
-
* The float64 reference is `renderDisplayView` (facade/display-view.ts) on the exact-area-mean path without
|
|
10
|
-
* diffraction, with the bilinear demosaic and chart materials. Internal: not exported from the package. The
|
|
11
|
-
* material lookup per query point is a module the caller supplies (`DisplayViewGpuMaterialModule`, the seam of
|
|
12
|
-
* #477); `display-view-chart-material-module.ts` provides one for the eight 2.0 chart presets and
|
|
13
|
-
* `display-view-composite-material-module.ts` (#491) one for composite charts, the 2.3 elements and `material-layers` scenes.
|
|
14
|
-
*/
|
|
15
|
-
import { type DisplayViewRenderResult, type DisplayViewSetup } from "../facade/display-view.js";
|
|
1
|
+
import { type DisplayViewKernelTap, type DisplayViewRenderResult, type DisplayViewSetup } from "../facade/display-view.js";
|
|
16
2
|
import { type DisplayViewExpectedSignalInput } from "../facade/expected-signal.js";
|
|
17
3
|
import { resolvePortableChartScene } from "../facade/chart-scenes.js";
|
|
18
4
|
import { type DisplayViewGpuConformanceCase, type DisplayViewGpuRenderer, type DisplayViewGpuRendererFactory, type DisplayViewGpuRequest } from "../facade/display-view-gpu.js";
|
|
@@ -90,7 +76,7 @@ export interface DisplayViewSpeedGpuResult extends DisplayViewRenderResult {
|
|
|
90
76
|
/**
|
|
91
77
|
* Why the kernel does not cover a request, or null when it does. The kernel is the Speed path: the exact area mean
|
|
92
78
|
* (views where a footprint holds at most 25 real pixels and at most K², and here at most 6 per axis), no diffraction
|
|
93
|
-
* kernels, chart materials, the bilinear demosaic (no AHD candidates
|
|
79
|
+
* kernels, chart materials, the bilinear demosaic (no AHD candidates), the identity or positive Reinhard
|
|
94
80
|
* tone curve, and at most 16 query offsets.
|
|
95
81
|
*/
|
|
96
82
|
export declare function displayViewSpeedGpuUnsupportedReason(setup: DisplayViewSetup, signalInput: DisplayViewExpectedSignalInput): string | null;
|
|
@@ -203,4 +189,18 @@ export declare const displayViewSpeedGpuRendererFactory: DisplayViewGpuRendererF
|
|
|
203
189
|
* registered before. Nothing registers it on import: the integration of #481 decides where the engine registers it.
|
|
204
190
|
*/
|
|
205
191
|
export declare function registerDisplayViewSpeedGpuRenderer(): DisplayViewGpuRendererFactory | null;
|
|
192
|
+
/** #564: the GPU refusal of a defocus kernel above the direct radius (the CPU convolves it by runs). */
|
|
193
|
+
export declare const LARGE_DEFOCUS_REASON = "a defocus kernel radius above 64 sites (convolved by runs on the CPU, #564) is not on the GPU";
|
|
194
|
+
/** The footprint shape of a view: real pixels per display pixel along each axis, and whether the exact area mean applies. */
|
|
195
|
+
export declare function footprintShape(setup: DisplayViewSetup): {
|
|
196
|
+
sx: number;
|
|
197
|
+
sy: number;
|
|
198
|
+
exact: boolean;
|
|
199
|
+
maximumColumns: number;
|
|
200
|
+
maximumRows: number;
|
|
201
|
+
};
|
|
202
|
+
/** The pixel-aperture samples per axis and anti-aliasing spots of a request. */
|
|
203
|
+
export declare function offsetCount(request: DisplayViewGpuRequest): number;
|
|
204
|
+
/** The bilinear RGGB demosaic kernels per phase (phaseY·2 + phaseX) and channel, as `bilinearPhaseProfiles` gives them. */
|
|
205
|
+
export declare function bilinearKernels(): DisplayViewKernelTap[][][];
|
|
206
206
|
export {};
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
* #477); `display-view-chart-material-module.ts` provides one for the eight 2.0 chart presets and
|
|
14
14
|
* `display-view-composite-material-module.ts` (#491) one for composite charts, the 2.3 elements and `material-layers` scenes.
|
|
15
15
|
*/
|
|
16
|
-
import {
|
|
16
|
+
import { SDR_LUMINANCE_WEIGHTS } from "../output/sdr-rendering.js";
|
|
17
|
+
import { DISPLAY_VIEW_NOISE_STREAM_ID, EXACT_AREA_MEAN_MAX_PIXELS, axisSums, clipCentre, createDisplayViewExpectedSignal, displayViewDecidedSaturation, overlaps, quantizationVariance, renderDisplayView } from "../facade/display-view.js";
|
|
17
18
|
import { displayViewSignalTables } from "../facade/expected-signal.js";
|
|
18
19
|
import { resolvePortableChartScene } from "../facade/chart-scenes.js";
|
|
19
20
|
import { setDisplayViewGpuRendererFactory } from "../facade/display-view-gpu.js";
|
|
@@ -25,7 +26,6 @@ import { createHostYieldGate } from "../capture/host-yield-cadence.js";
|
|
|
25
26
|
import { ImageKernelExecutionError, WEBGPU_F32_UNIT_ROUNDOFF, webGpuExecution } from "./image-kernel-execution.js";
|
|
26
27
|
import { BUFFER_USAGE, GpuResourceScope, abortedError, createComputePipeline, linearDispatch, runComputePass, throwIfAborted as checkAbort } from "./webgpu-runtime.js";
|
|
27
28
|
import { DISPLAY_VIEW_AUX, DISPLAY_VIEW_FLAG_WORDS, DISPLAY_VIEW_SPEED_MAXIMUM_NODES, DISPLAY_VIEW_GEOMETRY_STRIDE, DISPLAY_VIEW_GPU_MAXIMUM_OFFSETS, DISPLAY_VIEW_GPU_MAXIMUM_PIXELS_PER_AXIS, DISPLAY_VIEW_OUTPUT_FLOATS, DISPLAY_VIEW_PARAM_WORDS, DISPLAY_VIEW_REINHARD_MEAN_U, DISPLAY_VIEW_REINHARD_VARIANCE_U, DISPLAY_VIEW_WORKGROUP_SIZE, assembleDisplayViewSpeedWgsl } from "./wgsl-display-view-speed-kernel.js";
|
|
28
|
-
import { footprintShape, bilinearKernels, offsetCount } from "./display-view-quality-gpu.js";
|
|
29
29
|
/** One WGSL rounding of + − × in either direction (W3C WGSL "Floating Point Accuracy"; #471, #487): twice the binary32 unit roundoff. */
|
|
30
30
|
const E = 2 * WEBGPU_F32_UNIT_ROUNDOFF;
|
|
31
31
|
/** Higham's γ_k with E in place of u. */
|
|
@@ -53,7 +53,7 @@ const BYTES_PER_PIXEL = 4 * DISPLAY_VIEW_OUTPUT_FLOATS + 4 * DISPLAY_VIEW_FLAG_W
|
|
|
53
53
|
/**
|
|
54
54
|
* Why the kernel does not cover a request, or null when it does. The kernel is the Speed path: the exact area mean
|
|
55
55
|
* (views where a footprint holds at most 25 real pixels and at most K², and here at most 6 per axis), no diffraction
|
|
56
|
-
* kernels, chart materials, the bilinear demosaic (no AHD candidates
|
|
56
|
+
* kernels, chart materials, the bilinear demosaic (no AHD candidates), the identity or positive Reinhard
|
|
57
57
|
* tone curve, and at most 16 query offsets.
|
|
58
58
|
*/
|
|
59
59
|
export function displayViewSpeedGpuUnsupportedReason(setup, signalInput) {
|
|
@@ -65,10 +65,12 @@ export function displayViewSpeedGpuUnsupportedReason(setup, signalInput) {
|
|
|
65
65
|
return "radiance scenes (caller functions) are not on the GPU";
|
|
66
66
|
if (!signalInput.queryPoint)
|
|
67
67
|
return "the expected signal has no query points";
|
|
68
|
-
if (setup.candidates || setup.
|
|
69
|
-
return "AHD candidates
|
|
70
|
-
if (
|
|
68
|
+
if (setup.candidates || setup.ahdChoice)
|
|
69
|
+
return "AHD candidates are not on the GPU";
|
|
70
|
+
if (!GPU_TONE_CURVES.includes(setup.toneCurve))
|
|
71
71
|
return "unsupported tone curve " + String(setup.toneCurve);
|
|
72
|
+
if (setup.rendering && !setup.coupled)
|
|
73
|
+
return "the coupled rendering steps were not prepared";
|
|
72
74
|
if (signalInput.offsets.length < 1 || signalInput.offsets.length > DISPLAY_VIEW_GPU_MAXIMUM_OFFSETS)
|
|
73
75
|
return "the kernel holds 1 to " + DISPLAY_VIEW_GPU_MAXIMUM_OFFSETS + " query offsets";
|
|
74
76
|
if (signalInput.wavelengthsNm.length < 1 || signalInput.wavelengthsNm.length > DISPLAY_VIEW_SPEED_MAXIMUM_NODES)
|
|
@@ -168,6 +170,8 @@ export function axisRecord(geometry, at, start, end, limit, margin, scale) {
|
|
|
168
170
|
const order = ["bEven", "bOdd", "ppEven", "ppOdd", "qqEven", "qqOdd", "pqEven", "pqOdd", "ww"];
|
|
169
171
|
order.forEach((key, i) => { geometry[at + 8 + i] = sums[key] / scale2; });
|
|
170
172
|
}
|
|
173
|
+
/** The kernel's tone code: identity 0, positive Reinhard 1, extended Reinhard (luminance) 2, Naka–Rushton (luminance) 3. */
|
|
174
|
+
const TONE_CODE = { "identity": 0, "positive-reinhard-per-channel": 1, "extended-reinhard-luminance": 2, "naka-rushton-luminance": 3 };
|
|
171
175
|
/** The uniform parameters and the aux table of a render. */
|
|
172
176
|
function constants(setup, signalInput) {
|
|
173
177
|
const params = new ArrayBuffer(4 * DISPLAY_VIEW_PARAM_WORDS), words = new Uint32Array(params), floats = new Float32Array(params);
|
|
@@ -178,7 +182,7 @@ function constants(setup, signalInput) {
|
|
|
178
182
|
words[6] = setup.nativeWidth;
|
|
179
183
|
words[7] = setup.nativeHeight;
|
|
180
184
|
words[8] = setup.region.width;
|
|
181
|
-
words[9] = setup.toneCurve
|
|
185
|
+
words[9] = TONE_CODE[setup.toneCurve];
|
|
182
186
|
words[10] = signalInput.offsets.length;
|
|
183
187
|
words[11] = signalInput.wavelengthsNm.length;
|
|
184
188
|
for (let c = 0; c < 3; c++) {
|
|
@@ -298,12 +302,21 @@ export async function renderDisplayViewSpeedOnGpu(runtime, bandBytes, input, abo
|
|
|
298
302
|
const rows = Math.max(1, Math.min(region.height, Math.floor(bandBytes / (region.width * BYTES_PER_PIXEL)), material.bandRows?.(shape.sy) ?? Infinity));
|
|
299
303
|
if (Math.max(rows * region.width * 4 * DISPLAY_VIEW_OUTPUT_FLOATS, geometry.byteLength, table.byteLength) > runtime.maximumStorageBindingBytes)
|
|
300
304
|
throw new ImageKernelExecutionError("insufficient-limits", "One display-view band exceeds the device's storage binding limit.");
|
|
301
|
-
|
|
305
|
+
// #593, #601: the coupled steps' shader text and constants, loaded on demand for a view that asks for them.
|
|
306
|
+
const coupled = setup.rendering ? await import("./wgsl-display-view-coupled.js") : null;
|
|
307
|
+
const coupledConstants = coupled ? coupled.displayViewCoupledConstants(setup, SDR_LUMINANCE_WEIGHTS, gaussLegendre16()) : new Float32Array(1);
|
|
308
|
+
// #605: the neighbor reconstruction's ratios from the host, in a second dispatch per band (wgsl-display-view-neighbors.ts).
|
|
309
|
+
const neighbors = setup.coupled?.neighbors && coupled;
|
|
310
|
+
const pipeline = await pipelines("photivra-display-view-speed:" + material.id + (coupled ? "+coupled" : "") + (neighbors ? "+neighbors" : ""), assembleDisplayViewSpeedWgsl(material.wgsl, coupled?.displayViewCoupledWgsl(!!neighbors)));
|
|
302
311
|
const moments = new Float32Array(pixelCount * DISPLAY_VIEW_OUTPUT_FLOATS), flagged = [], flagWords = new Uint32Array(pixelCount * DISPLAY_VIEW_FLAG_WORDS);
|
|
303
312
|
const words = new Uint32Array(params);
|
|
304
313
|
const scope = new GpuResourceScope(runtime);
|
|
305
314
|
try {
|
|
306
|
-
|
|
315
|
+
// #593, #601: the coupled steps' constants follow the aux table's own entries (one zero word without them).
|
|
316
|
+
const auxWithCoupled = new Float32Array(aux.length + coupledConstants.length);
|
|
317
|
+
auxWithCoupled.set(aux);
|
|
318
|
+
auxWithCoupled.set(coupledConstants, aux.length);
|
|
319
|
+
const auxBuffer = scope.upload("photivra-display-view-aux", auxWithCoupled, BUFFER_USAGE.STORAGE);
|
|
307
320
|
const geometryBuffer = scope.upload("photivra-display-view-geometry", geometry, BUFFER_USAGE.STORAGE);
|
|
308
321
|
const tableBuffer = scope.upload("photivra-display-view-table", table, BUFFER_USAGE.STORAGE);
|
|
309
322
|
const materialGroup = material.band ? null : runtime.device.createBindGroup({ layout: pipeline.getBindGroupLayout(1), entries: material.bindings.map((b) => ({ binding: b.binding,
|
|
@@ -317,16 +330,21 @@ export async function renderDisplayViewSpeedOnGpu(runtime, bandBytes, input, abo
|
|
|
317
330
|
const band = new GpuResourceScope(runtime);
|
|
318
331
|
try {
|
|
319
332
|
const out = band.buffer("photivra-display-view-moments", count * 4 * DISPLAY_VIEW_OUTPUT_FLOATS, BUFFER_USAGE.STORAGE | BUFFER_USAGE.COPY_SRC);
|
|
320
|
-
const flagBuffer = band.buffer("photivra-display-view-flags", count * 4 * DISPLAY_VIEW_FLAG_WORDS, BUFFER_USAGE.STORAGE | BUFFER_USAGE.COPY_SRC);
|
|
321
333
|
const uniform = band.upload("photivra-display-view-params", new Uint8Array(params), BUFFER_USAGE.UNIFORM);
|
|
322
|
-
const bindGroup = runtime.device.createBindGroup({ layout: pipeline.getBindGroupLayout(0), entries: [
|
|
323
|
-
{ binding: 0, resource: { buffer: uniform } }, { binding: 1, resource: { buffer: auxBuffer } }, { binding: 2, resource: { buffer: geometryBuffer } },
|
|
324
|
-
{ binding: 3, resource: { buffer: tableBuffer } }, { binding: 4, resource: { buffer: out } }, { binding: 5, resource: { buffer: flagBuffer } }
|
|
325
|
-
] });
|
|
326
334
|
// #581: a module that bands its own data (a large photo) gives group 1 per band, for the native rows the band reads (with margin).
|
|
327
|
-
const
|
|
335
|
+
const group1 = materialGroup ?? material.band(band, pipeline.getBindGroupLayout(1), Math.floor((region.y + row0) * shape.sy) + margin - 2, Math.ceil((region.y + row1) * shape.sy) + margin + 2);
|
|
336
|
+
let data, flagData;
|
|
337
|
+
const run = async (contents = new Uint32Array(count * DISPLAY_VIEW_FLAG_WORDS)) => {
|
|
338
|
+
const flagBuffer = band.upload("photivra-display-view-flags", contents, BUFFER_USAGE.STORAGE | BUFFER_USAGE.COPY_SRC);
|
|
339
|
+
const bindGroup = runtime.device.createBindGroup({ layout: pipeline.getBindGroupLayout(0), entries: [
|
|
340
|
+
{ binding: 0, resource: { buffer: uniform } }, { binding: 1, resource: { buffer: auxBuffer } }, { binding: 2, resource: { buffer: geometryBuffer } },
|
|
341
|
+
{ binding: 3, resource: { buffer: tableBuffer } }, { binding: 4, resource: { buffer: out } }, { binding: 5, resource: { buffer: flagBuffer } }
|
|
342
|
+
] });
|
|
343
|
+
[data, flagData] = await runComputePass(runtime, band, pipeline, [bindGroup, group1], linearDispatch(count, DISPLAY_VIEW_WORKGROUP_SIZE, runtime.maximumWorkgroupsPerDimension), [{ buffer: out, bytes: count * 4 * DISPLAY_VIEW_OUTPUT_FLOATS }, { buffer: flagBuffer, bytes: count * 4 * DISPLAY_VIEW_FLAG_WORDS }], abort.signal);
|
|
344
|
+
return new Uint32Array(flagData, 0, count * DISPLAY_VIEW_FLAG_WORDS);
|
|
345
|
+
};
|
|
346
|
+
const bandFlags = neighbors ? await neighbors.dispatchWithNeighborRatios(setup, geometry, first, count, runtime.maximumStorageBindingBytes, run) : await run();
|
|
328
347
|
moments.set(new Float32Array(data, 0, count * DISPLAY_VIEW_OUTPUT_FLOATS), first * DISPLAY_VIEW_OUTPUT_FLOATS);
|
|
329
|
-
const bandFlags = new Uint32Array(flagData, 0, count * DISPLAY_VIEW_FLAG_WORDS);
|
|
330
348
|
flagWords.set(bandFlags, first * DISPLAY_VIEW_FLAG_WORDS);
|
|
331
349
|
for (let i = 0; i < count; i++) {
|
|
332
350
|
let flag = (bandFlags[DISPLAY_VIEW_FLAG_WORDS * i] & 1) !== 0;
|
|
@@ -409,7 +427,7 @@ export async function renderDisplayViewSpeedOnGpu(runtime, bandBytes, input, abo
|
|
|
409
427
|
saturatedPixelCount += saturated[i];
|
|
410
428
|
const expectedValueBound = { kind: "relative-to-reference", relative: relative.mean, absolute: largestMean };
|
|
411
429
|
const uncertain = flagged.length - recomputed.length + undecided.length - highlights.length;
|
|
412
|
-
return { samples, expected, noiseStd, sampleCount, siteCount, detailPixelCount: pixelCount, uniformPixelCount: 0,
|
|
430
|
+
return { samples, expected, noiseStd, sampleCount, siteCount, detailPixelCount: pixelCount, uniformPixelCount: 0, estimation: "exact-area-mean", saturated, saturatedPixelCount,
|
|
413
431
|
execution: webGpuExecution(expectedValueBound, uncertain), expectedValueBound,
|
|
414
432
|
varianceBound: { kind: "relative-to-reference", relative: relative.variance, absolute: largestVariance },
|
|
415
433
|
expectedValueAbsoluteBound: meanBound, varianceAbsoluteBound: varianceBound,
|
|
@@ -434,12 +452,15 @@ export function displayViewSpeedGpuSupports(request) {
|
|
|
434
452
|
export function sceneToneAndOffsetsReason(request, maximumOffsets) {
|
|
435
453
|
if (request.scene !== "chart" && request.scene !== "material-layers" && request.scene !== "image-plane")
|
|
436
454
|
return "the scene is a caller " + request.scene + "; the GPU material lookup covers engine charts and declared material-layers scenes (describe the scene as material-layers)";
|
|
437
|
-
|
|
455
|
+
// #593: the identity, Reinhard and the two luminance tone curves (the luminance curves through the coupled steps).
|
|
456
|
+
if (!GPU_TONE_CURVES.includes(request.toneCurve))
|
|
438
457
|
return "unsupported tone curve " + String(request.toneCurve);
|
|
439
458
|
if (offsetCount(request) > maximumOffsets)
|
|
440
459
|
return "more than " + maximumOffsets + " query offsets per site";
|
|
441
460
|
return true;
|
|
442
461
|
}
|
|
462
|
+
/** The tone curves the GPU kernels render (#593 adds the luminance curves). */
|
|
463
|
+
const GPU_TONE_CURVES = ["identity", "positive-reinhard-per-channel", "extended-reinhard-luminance", "naka-rushton-luminance"];
|
|
443
464
|
/**
|
|
444
465
|
* A self-check's verdict: every component of a GPU render inside its a-priori bounds against the reference, every sample within
|
|
445
466
|
* one code, and (#533) the saturated-pixel count the reference's bit for bit; true, or a sentence saying where it failed.
|
|
@@ -548,7 +569,7 @@ export function createDisplayViewSpeedGpuRenderer(runtime, options = {}) {
|
|
|
548
569
|
const material = await modules.moduleFor(setup.gpu, abort.signal);
|
|
549
570
|
const result = await renderDisplayViewSpeedOnGpu(runtime, bandBytes, { setup, signalInput: setup.gpu.signalInput, material }, abort, options.yieldControl, source);
|
|
550
571
|
return { samples: result.samples, expected: result.expected, noiseStd: result.noiseStd, sampleCount: result.sampleCount, siteCount: result.siteCount, detailPixelCount: result.detailPixelCount,
|
|
551
|
-
uniformPixelCount: result.uniformPixelCount,
|
|
572
|
+
uniformPixelCount: result.uniformPixelCount, estimation: result.estimation, saturated: result.saturated,
|
|
552
573
|
saturatedPixelCount: result.saturatedPixelCount, errorBound: result.expectedValueBound,
|
|
553
574
|
diagnosticUncertaintySampleCount: result.execution.diagnosticUncertaintySampleCount, ...(material.compositeProbe ? { compositeProbe: material.compositeProbe } : {}) };
|
|
554
575
|
}
|
|
@@ -568,4 +589,26 @@ export const displayViewSpeedGpuRendererFactory = (handle) => createDisplayViewS
|
|
|
568
589
|
export function registerDisplayViewSpeedGpuRenderer() {
|
|
569
590
|
return setDisplayViewGpuRendererFactory(displayViewSpeedGpuRendererFactory);
|
|
570
591
|
}
|
|
592
|
+
// #594: shared with the on-demand Quality host (display-view-quality-gpu.ts), so the Speed path does not import it.
|
|
593
|
+
/** #564: the GPU refusal of a defocus kernel above the direct radius (the CPU convolves it by runs). */
|
|
594
|
+
export const LARGE_DEFOCUS_REASON = "a defocus kernel radius above 64 sites (convolved by runs on the CPU, #564) is not on the GPU";
|
|
595
|
+
/** The footprint shape of a view: real pixels per display pixel along each axis, and whether the exact area mean applies. */
|
|
596
|
+
export function footprintShape(setup) {
|
|
597
|
+
const sx = setup.frameWidth / setup.viewWidth, sy = setup.frameHeight / setup.viewHeight, area = sx * sy;
|
|
598
|
+
const exact = area <= Math.min(EXACT_AREA_MEAN_MAX_PIXELS, setup.samplesPerAxis * setup.samplesPerAxis);
|
|
599
|
+
let maximumColumns = 0, maximumRows = 0;
|
|
600
|
+
for (let i = 0; i < setup.region.width; i++)
|
|
601
|
+
maximumColumns = Math.max(maximumColumns, overlaps((setup.region.x + i) * sx, (setup.region.x + i + 1) * sx, setup.frameWidth).w.length);
|
|
602
|
+
for (let j = 0; j < setup.region.height; j++)
|
|
603
|
+
maximumRows = Math.max(maximumRows, overlaps((setup.region.y + j) * sy, (setup.region.y + j + 1) * sy, setup.frameHeight).w.length);
|
|
604
|
+
return { sx, sy, exact, maximumColumns, maximumRows };
|
|
605
|
+
}
|
|
606
|
+
/** The pixel-aperture samples per axis and anti-aliasing spots of a request. */
|
|
607
|
+
export function offsetCount(request) { return request.boxSamples * request.boxSamples * (request.antiAliasing ? 4 : 1); }
|
|
608
|
+
/** The bilinear RGGB demosaic kernels per phase (phaseY·2 + phaseX) and channel, as `bilinearPhaseProfiles` gives them. */
|
|
609
|
+
export function bilinearKernels() {
|
|
610
|
+
const cross = [[1, 0], [-1, 0], [0, 1], [0, -1]], diagonal = [[1, 1], [1, -1], [-1, 1], [-1, -1]], horizontal = [[1, 0], [-1, 0]], vertical = [[0, 1], [0, -1]];
|
|
611
|
+
const average = (offsets) => offsets.map(([dx, dy]) => ({ dx: dx, dy: dy, weight: 1 / offsets.length })), self = [{ dx: 0, dy: 0, weight: 1 }];
|
|
612
|
+
return [[self, average(cross), average(diagonal)], [average(horizontal), self, average(vertical)], [average(vertical), self, average(horizontal)], [average(diagonal), average(cross), self]];
|
|
613
|
+
}
|
|
571
614
|
//# sourceMappingURL=display-view-speed-gpu.js.map
|