@photivra/engine 2.13.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 +68 -1
- package/CITATION.cff +1 -1
- package/README.md +7 -7
- package/SECURITY.md +1 -1
- package/THIRD_PARTY.md +2 -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/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.js +2 -1
- package/dist/exposure/auto-iso-slowest-shutter.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/display-view-gpu.js +1 -1
- package/dist/facade/display-view-gpu.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 +47 -3
- package/dist/facade/simulate-capture.js +71 -22
- 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/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.js +505 -505
- 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 +5 -3
- package/dist/index.js +4 -2
- 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.js +1 -1
- 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 +1 -1
- package/dist/output/print-jpeg.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 +29 -1
- package/docs/QUICK_START.md +40 -5
- package/docs/USAGE.md +35 -1
- 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 +107 -2
- 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 +52 -2
- package/llms.txt +1 -0
- package/package.json +2 -2
|
@@ -42,7 +42,7 @@ export const SENSOR_OUTPUT = Object.freeze({ codeMask: 0xffff, flagShift: 16, un
|
|
|
42
42
|
* each: the integer mantissa m (< 2^12), the exponent s and the exact scale 2^s, so that piece = m·2^s. The INL
|
|
43
43
|
* table holds the knot codes, the knot offsets and the host-computed segment slopes.
|
|
44
44
|
*/
|
|
45
|
-
export const SENSOR_AUX = Object.freeze({ stirlingRemainder: 0, sigma: 256, inversePieces: 272, digitalPieces: 284, knots: 296 });
|
|
45
|
+
export const SENSOR_AUX = /* @__PURE__ */ Object.freeze({ stirlingRemainder: 0, sigma: 256, inversePieces: 272, digitalPieces: 284, knots: 296 });
|
|
46
46
|
export const SENSOR_PIECE_WORDS = 3;
|
|
47
47
|
export const SENSOR_WORKGROUP_SIZE = 256;
|
|
48
48
|
/**
|
|
@@ -52,11 +52,11 @@ export const SENSOR_WORKGROUP_SIZE = 256;
|
|
|
52
52
|
*/
|
|
53
53
|
export const SENSOR_SITE_WORDS = 4;
|
|
54
54
|
/** Bits of `Params.extras`. */
|
|
55
|
-
export const SENSOR_EXTRAS = Object.freeze({ deterministic: 1, fixedPattern: 2 });
|
|
55
|
+
export const SENSOR_EXTRAS = /* @__PURE__ */ Object.freeze({ deterministic: 1, fixedPattern: 2 });
|
|
56
56
|
/** Partial charge sums saturate here: above every supported capacity (2^24), so no decision changes. */
|
|
57
57
|
export const SENSOR_REALIZED_CLAMP = 2 ** 30;
|
|
58
58
|
/** Mean categories in bits 30–31 of a mean word, mirroring `samplePoisson`'s branches. */
|
|
59
|
-
export const SENSOR_MEAN_CATEGORY = Object.freeze({ zero: 0, multiplication: 1, transformedRejection: 2, normal: 3 });
|
|
59
|
+
export const SENSOR_MEAN_CATEGORY = /* @__PURE__ */ Object.freeze({ zero: 0, multiplication: 1, transformedRejection: 2, normal: 3 });
|
|
60
60
|
/** One WGSL rounding (one ULP, either direction) is at most this relative error: 2^-23. */
|
|
61
61
|
export const SENSOR_ROUNDING = 2 ** -23;
|
|
62
62
|
/** |z_f32 − z_f64| ≤ SENSOR_NORMAL_ERROR·E·radius for the Box–Muller normal (docs/WEBGPU.md). */
|
|
@@ -80,14 +80,14 @@ const CPU_REL: f32 = 7.105427357601002e-15;
|
|
|
80
80
|
const LOG_ABS: f32 = 4.76837158203125e-7;
|
|
81
81
|
const Z_ERR: f32 = ${literal(SENSOR_NORMAL_ERROR)};
|
|
82
82
|
struct Params {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
83
|
+
count: u32, row0: u32, region_w: u32, native_w: u32,
|
|
84
|
+
region_x: u32, region_y: u32, seed: u32, components: u32,
|
|
85
|
+
knots: u32, digital: u32, saturation: u32, adc_max: u32,
|
|
86
|
+
capacity_floor: u32, threshold_floor: u32, black: u32, sat_quantized: i32,
|
|
87
|
+
capacity_frac: f32, threshold_frac: f32, inv_gain: f32, inv_residual: f32,
|
|
88
|
+
digital_gain: f32, digital_residual: f32, inl_slope: f32, inl_offset: f32,
|
|
89
|
+
site_words: u32, poisson_count: u32, extras: u32, pad0: u32,
|
|
90
|
+
fpn_e_slack: f32, fpn_c_slack: f32, inl_knot: f32, pad2: f32,
|
|
91
91
|
};
|
|
92
92
|
@group(0) @binding(0) var<uniform> params: Params;
|
|
93
93
|
@group(0) @binding(1) var<storage, read> means: array<u32>;
|
|
@@ -101,352 +101,352 @@ var<private> ip: i32;
|
|
|
101
101
|
var<private> fp: f32;
|
|
102
102
|
|
|
103
103
|
fn fmix(value: u32) -> u32 {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
var h = value;
|
|
105
|
+
h = h ^ (h >> 16u); h = h * 0x85ebca6bu; h = h ^ (h >> 13u); h = h * 0xc2b2ae35u; h = h ^ (h >> 16u);
|
|
106
|
+
return h;
|
|
107
107
|
}
|
|
108
108
|
fn mix_block(hash: u32, block: u32) -> u32 {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
109
|
+
var k = block * 0xcc9e2d51u;
|
|
110
|
+
k = (k << 15u) | (k >> 17u);
|
|
111
|
+
k = k * 0x1b873593u;
|
|
112
|
+
var h = hash ^ k;
|
|
113
|
+
h = (h << 13u) | (h >> 19u);
|
|
114
|
+
return h * 5u + 0xe6546b64u;
|
|
115
115
|
}
|
|
116
116
|
fn site_seed(seed: u32, index: u32, stream: u32) -> u32 {
|
|
117
|
-
|
|
117
|
+
return fmix(mix_block(mix_block(mix_block(0u, seed), index), stream) ^ 12u);
|
|
118
118
|
}
|
|
119
119
|
fn start(seed: u32) {
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
state = fmix(seed ^ 0x9e3779b9u);
|
|
121
|
+
if (state == 0u) { state = 0x6d2b79f5u; }
|
|
122
122
|
}
|
|
123
123
|
fn next_bits() -> u32 {
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
state = state ^ (state << 13u); state = state ^ (state >> 17u); state = state ^ (state << 5u);
|
|
125
|
+
return state;
|
|
126
126
|
}
|
|
127
|
-
|
|
127
|
+
|
|
128
128
|
fn unit(bits: u32) -> f32 { return (f32(bits) + 0.5) * INV32; }
|
|
129
129
|
fn check(distance: f32, margin: f32) { if (abs(distance) <= margin) { uncertain = true; } }
|
|
130
130
|
|
|
131
|
-
|
|
132
|
-
|
|
131
|
+
|
|
132
|
+
|
|
133
133
|
fn ln_unit(bits: u32) -> f32 {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
134
|
+
if (bits < 0x80000000u) { return log(unit(bits)); }
|
|
135
|
+
let w = (f32(0xffffffffu - bits) + 0.5) * INV32;
|
|
136
|
+
let r = -w / (2.0 - w);
|
|
137
|
+
let r2 = r * r;
|
|
138
138
|
var p = ${literal(1 / 23)};
|
|
139
139
|
${[21, 19, 17, 15, 13, 11, 9, 7, 5, 3].map(n => `p = p * r2 + ${literal(1 / n)};`).join(" ")}
|
|
140
|
-
|
|
141
|
-
|
|
140
|
+
p = p * r2 + 1.0;
|
|
141
|
+
return 2.0 * r * p;
|
|
142
142
|
}
|
|
143
|
-
|
|
143
|
+
|
|
144
144
|
fn cos_unit(bits: u32) -> f32 {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
145
|
+
let octant = bits >> 29u;
|
|
146
|
+
let low = bits & 0x1fffffffu;
|
|
147
|
+
let even = (octant & 1u) == 0u;
|
|
148
|
+
var g = (f32(0x1fffffffu - low) + 0.5) * TWO_PI_INV32;
|
|
149
|
+
if (even) { g = (f32(low) + 0.5) * TWO_PI_INV32; }
|
|
150
|
+
let g2 = g * g;
|
|
151
151
|
var c = ${literal(COS_COEFFICIENTS[5])};
|
|
152
152
|
${[4, 3, 2, 1, 0].map(j => `c = c * g2 + ${literal(COS_COEFFICIENTS[j])};`).join(" ")}
|
|
153
|
-
|
|
153
|
+
c = c * g2 + 1.0;
|
|
154
154
|
var s = ${literal(SIN_COEFFICIENTS[4])};
|
|
155
155
|
${[3, 2, 1, 0].map(j => `s = s * g2 + ${literal(SIN_COEFFICIENTS[j])};`).join(" ")}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
|
|
156
|
+
s = g * (s * g2 + 1.0);
|
|
157
|
+
let cb = select(s, c, even);
|
|
158
|
+
let sb = select(c, s, even);
|
|
159
|
+
let q = octant >> 1u;
|
|
160
|
+
if (q == 0u) { return cb; }
|
|
161
|
+
if (q == 1u) { return -sb; }
|
|
162
|
+
if (q == 2u) { return -cb; }
|
|
163
|
+
return sb;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
|
|
167
167
|
fn std_normal() -> f32 {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
168
|
+
let b1 = next_bits();
|
|
169
|
+
let b2 = next_bits();
|
|
170
|
+
radius = sqrt(-2.0 * ln_unit(b1));
|
|
171
|
+
return radius * cos_unit(b2);
|
|
172
172
|
}
|
|
173
|
-
|
|
174
|
-
|
|
173
|
+
|
|
174
|
+
|
|
175
175
|
fn poisson_small(mean: f32) -> u32 {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}
|
|
188
|
-
|
|
176
|
+
let threshold = exp(-mean);
|
|
177
|
+
var product = 1.0;
|
|
178
|
+
var count = 0u;
|
|
179
|
+
loop {
|
|
180
|
+
count = count + 1u;
|
|
181
|
+
product = product * unit(next_bits());
|
|
182
|
+
check(product - threshold, MARGIN * (3.0 * f32(count) + 4.0 + 3.0 * mean) * E * max(product, threshold));
|
|
183
|
+
if (!(product > threshold)) { break; }
|
|
184
|
+
if (count >= 1000u) { uncertain = true; break; }
|
|
185
|
+
}
|
|
186
|
+
return count - 1u;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
189
|
fn log1p_minus(t: f32) -> f32 {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
190
|
+
let d = 2.0 + t;
|
|
191
|
+
let s = t / d;
|
|
192
|
+
let s2 = s * s;
|
|
193
193
|
var p = ${literal(1 / 25)};
|
|
194
194
|
${[23, 21, 19, 17, 15, 13, 11, 9, 7, 5].map(n => `p = p * s2 + ${literal(1 / n)};`).join(" ")}
|
|
195
195
|
p = p * s2 + ${literal(1 / 3)};
|
|
196
|
-
|
|
196
|
+
return -(t * t) / d + 2.0 * s * s2 * p;
|
|
197
197
|
}
|
|
198
198
|
fn poisson_ptrs(mi: u32, mf: f32) -> u32 {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
199
|
+
|
|
200
|
+
let mean = f32(mi) + mf;
|
|
201
|
+
let sq = sqrt(mean);
|
|
202
|
+
let b = 0.931 + 2.53 * sq;
|
|
203
|
+
let a = -0.059 + 0.02483 * b;
|
|
204
|
+
let inv_alpha = 1.1239 + 1.1328 / (b - 3.4);
|
|
205
|
+
let v_r = 0.9277 - 3.6224 / (b - 2.0);
|
|
206
|
+
let ln_mean = log(mean);
|
|
207
|
+
for (var iteration = 0u; iteration < 64u; iteration = iteration + 1u) {
|
|
208
|
+
let su = next_bits();
|
|
209
|
+
let sv = next_bits();
|
|
210
|
+
var m = su;
|
|
211
|
+
var sign = -1.0;
|
|
212
|
+
if (su >= 0x80000000u) { m = 0xffffffffu - su; sign = 1.0; }
|
|
213
|
+
let us = unit(m);
|
|
214
|
+
let u = sign * unit(0x7fffffffu - m);
|
|
215
|
+
let v = unit(sv);
|
|
216
|
+
|
|
217
|
+
let scale = 2.0 * a / us + b;
|
|
218
|
+
let t = scale * u;
|
|
219
|
+
let x = (t + mf) + 0.43;
|
|
220
|
+
let fl = floor(x);
|
|
221
|
+
let ex = MARGIN * (25.0 * E * abs(t) + 4.0 * E + 4.5e-16 * (abs(t) + mean + 1.0));
|
|
222
|
+
if (x - fl <= ex || fl + 1.0 - x <= ex) { uncertain = true; }
|
|
223
|
+
if (fl <= -1073741824.0 || fl >= 1073741824.0) { continue; }
|
|
224
|
+
let k = i32(mi) + i32(fl);
|
|
225
225
|
if (m >= ${uniformThresholdInteger(0.07)}u) {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
226
|
+
if (k >= 0) { check(v - v_r, MARGIN * (7.0 * E + 2.0 * E * v)); }
|
|
227
|
+
if (v <= v_r && k >= 0) { return u32(k); }
|
|
228
|
+
}
|
|
229
229
|
if (k < 0 || (m < ${uniformThresholdInteger(0.013)}u && sv > m)) { continue; }
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
230
|
+
|
|
231
|
+
let lhs = log(v * inv_alpha / (a / (us * us) + b));
|
|
232
|
+
let dl = 32.0 * E + LOG_ABS + 3.0 * E * abs(lhs);
|
|
233
|
+
var rhs: f32;
|
|
234
|
+
var dr: f32;
|
|
235
|
+
if (k == 0) {
|
|
236
|
+
rhs = -mean;
|
|
237
|
+
dr = 3.0 * E * mean + CPU_REL * mean;
|
|
238
|
+
} else {
|
|
239
|
+
let kf = f32(k);
|
|
240
|
+
let dd = f32(i32(mi) - k) + mf;
|
|
241
|
+
let t2 = dd / kf;
|
|
242
|
+
var kg: f32;
|
|
243
|
+
var dk: f32;
|
|
244
|
+
if (abs(t2) <= 0.5) {
|
|
245
|
+
kg = kf * log1p_minus(t2);
|
|
246
|
+
dk = 25.0 * E * abs(kg) + E;
|
|
247
|
+
} else {
|
|
248
|
+
let lr = log(mean / kf);
|
|
249
|
+
kg = kf * lr - dd;
|
|
250
|
+
dk = kf * (6.0 * E + LOG_ABS + 5.0 * E * abs(lr)) + 2.0 * E * abs(dd) + E + E * abs(kg);
|
|
251
|
+
}
|
|
252
|
+
let lnk = log(kf);
|
|
253
|
+
var corr: f32;
|
|
254
|
+
if (k < 256) { corr = aux[u32(k)]; } else { corr = 1.0 / (12.0 * kf) - 1.0 / (360.0 * kf * kf * kf); }
|
|
255
|
+
rhs = ((kg - 0.5 * lnk) - 0.91893853320467274) - corr;
|
|
256
|
+
dr = dk + 0.5 * LOG_ABS + 1.5 * E * lnk + 2.0 * E + 3.0 * E * (abs(kg) + 0.5 * lnk + 1.0) +
|
|
257
|
+
CPU_REL * (mean + kf * (abs(ln_mean) + lnk + 1.0));
|
|
258
|
+
}
|
|
259
|
+
check(lhs - rhs, MARGIN * (dl + dr));
|
|
260
|
+
if (lhs <= rhs) { return u32(k); }
|
|
261
|
+
}
|
|
262
|
+
uncertain = true;
|
|
263
|
+
return mi;
|
|
264
264
|
}
|
|
265
265
|
fn poisson(word: u32, frac: f32) -> u32 {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
|
|
266
|
+
let category = word >> 30u;
|
|
267
|
+
let mi = word & 0x3fffffffu;
|
|
268
|
+
if (category == 0u) { return 0u; }
|
|
269
|
+
if (category == 1u) { return poisson_small(f32(mi) + frac); }
|
|
270
|
+
if (category == 2u) { return poisson_ptrs(mi, frac); }
|
|
271
|
+
|
|
272
|
+
let z = std_normal();
|
|
273
|
+
let y = sqrt(f32(mi) + frac) * z + frac + 0.5;
|
|
274
|
+
return u32(max(0, i32(mi) + i32(floor(y))));
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
|
|
278
278
|
fn add_scaled(product: u32, s: i32, scale: f32) {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
|
|
279
|
+
if (product == 0u) { return; }
|
|
280
|
+
|
|
281
|
+
if (s >= 0) { ip = ip + i32(product << u32(s)); return; }
|
|
282
|
+
if (s <= -24) { fp = fp + f32(product) * scale; return; }
|
|
283
|
+
let shift = u32(-s);
|
|
284
|
+
ip = ip + i32(product >> shift);
|
|
285
|
+
fp = fp + f32(product & ((1u << shift) - 1u)) * scale;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
|
|
289
289
|
fn scaled(n: u32, base: u32) {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
290
|
+
let hi = n >> 12u;
|
|
291
|
+
let lo = n & 0xfffu;
|
|
292
|
+
for (var j = 0u; j < 4u; j = j + 1u) {
|
|
293
293
|
let m = u32(aux[base + ${SENSOR_PIECE_WORDS}u * j]);
|
|
294
294
|
let s = i32(aux[base + ${SENSOR_PIECE_WORDS}u * j + 1u]);
|
|
295
295
|
let scale = aux[base + ${SENSOR_PIECE_WORDS}u * j + 2u];
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
296
|
+
add_scaled(hi * m, s + 12, scale * 4096.0);
|
|
297
|
+
add_scaled(lo * m, s, scale);
|
|
298
|
+
}
|
|
299
299
|
}
|
|
300
300
|
fn normalize() {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
301
|
+
let f = floor(fp);
|
|
302
|
+
ip = ip + i32(f);
|
|
303
|
+
fp = fp - f;
|
|
304
304
|
}
|
|
305
|
-
|
|
305
|
+
|
|
306
306
|
fn inl_offset(code: f32) -> f32 {
|
|
307
|
-
|
|
307
|
+
let n = params.knots;
|
|
308
308
|
let base = ${SENSOR_AUX.knots}u;
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
309
|
+
if (code <= aux[base]) { return aux[base + n]; }
|
|
310
|
+
if (code >= aux[base + n - 1u]) { return aux[base + 2u * n - 1u]; }
|
|
311
|
+
var low = 0u;
|
|
312
|
+
var high = n - 1u;
|
|
313
|
+
loop {
|
|
314
|
+
if (high - low <= 1u) { break; }
|
|
315
|
+
let middle = (low + high) >> 1u;
|
|
316
|
+
if (aux[base + middle] <= code) { low = middle; } else { high = middle; }
|
|
317
|
+
}
|
|
318
|
+
return aux[base + n + low] + (code - aux[base + low]) * aux[base + 2u * n + low];
|
|
319
319
|
}
|
|
320
320
|
@compute @workgroup_size(${SENSOR_WORKGROUP_SIZE})
|
|
321
321
|
fn main(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgroups) groups: vec3<u32>) {
|
|
322
322
|
let i = gid.x + gid.y * groups.x * ${SENSOR_WORKGROUP_SIZE}u;
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
323
|
+
if (i >= params.count) { return; }
|
|
324
|
+
let row = params.row0 + i / params.region_w;
|
|
325
|
+
let index = (params.region_y + row) * params.native_w + params.region_x + i % params.region_w;
|
|
326
|
+
uncertain = false;
|
|
327
|
+
let base = i * params.site_words;
|
|
328
|
+
start(site_seed(params.seed, index, 0u));
|
|
329
|
+
let photo = poisson(means[base], bitcast<f32>(means[base + 1u]));
|
|
330
|
+
let dark = poisson(means[base + 2u], bitcast<f32>(means[base + 3u]));
|
|
331
|
+
|
|
332
332
|
var realized = min(photo + dark, ${SENSOR_REALIZED_CLAMP}u);
|
|
333
|
-
|
|
333
|
+
for (var k = 0u; k < params.poisson_count; k = k + 1u) {
|
|
334
334
|
realized = min(realized + poisson(means[base + 4u + 2u * k], bitcast<f32>(means[base + 5u + 2u * k])), ${SENSOR_REALIZED_CLAMP}u);
|
|
335
|
-
|
|
336
|
-
|
|
335
|
+
}
|
|
336
|
+
var cursor = base + 4u + 2u * params.poisson_count;
|
|
337
337
|
let deterministic = (params.extras & ${SENSOR_EXTRAS.deterministic}u) != 0u;
|
|
338
338
|
let pattern = (params.extras & ${SENSOR_EXTRAS.fixedPattern}u) != 0u;
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
339
|
+
var r_frac = 0.0;
|
|
340
|
+
var det_slack = 0.0;
|
|
341
|
+
if (deterministic) {
|
|
342
342
|
realized = min(realized + means[cursor], ${SENSOR_REALIZED_CLAMP}u);
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
343
|
+
r_frac = bitcast<f32>(means[cursor + 1u]);
|
|
344
|
+
det_slack = E;
|
|
345
|
+
cursor = cursor + 2u;
|
|
346
|
+
}
|
|
347
|
+
var t_floor = i32(params.threshold_floor);
|
|
348
|
+
var t_frac = params.threshold_frac;
|
|
349
|
+
var fpn_e_slack = 0.0;
|
|
350
|
+
if (pattern) {
|
|
351
|
+
t_floor = bitcast<i32>(means[cursor]);
|
|
352
|
+
t_frac = bitcast<f32>(means[cursor + 1u]);
|
|
353
|
+
fpn_e_slack = params.fpn_e_slack;
|
|
354
|
+
}
|
|
355
|
+
start(site_seed(params.seed, index, 1u));
|
|
356
|
+
var noise = 0.0;
|
|
357
|
+
var noise_bound = 0.0;
|
|
358
|
+
for (var c = 0u; c < params.components; c = c + 1u) {
|
|
359
|
+
let sigma = aux[256u + c];
|
|
360
|
+
if (sigma != 0.0) {
|
|
361
|
+
let z = std_normal();
|
|
362
|
+
noise = noise + z * sigma;
|
|
363
|
+
|
|
364
|
+
noise_bound = noise_bound + sigma * radius * (Z_ERR + 2.0 + f32(params.components)) * E;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
var flags = 0u;
|
|
368
|
+
var a_int = realized;
|
|
369
|
+
var a_frac = r_frac;
|
|
370
|
+
if (!deterministic) {
|
|
371
|
+
if (realized > params.capacity_floor) { flags = 1u; a_int = params.capacity_floor; a_frac = params.capacity_frac; }
|
|
372
|
+
} else {
|
|
373
|
+
|
|
374
|
+
let w = f32(i32(realized) - i32(params.capacity_floor));
|
|
375
|
+
let dcap = w + (r_frac - params.capacity_frac);
|
|
376
|
+
check(dcap, MARGIN * (3.0 * E * abs(w) + 6.0 * E + CPU_REL * (f32(realized) + 1.0)));
|
|
377
|
+
if (dcap > 0.0) { flags = 1u; a_int = params.capacity_floor; a_frac = params.capacity_frac; }
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
let whole = f32(i32(a_int) - t_floor);
|
|
382
|
+
let diff = (whole + (a_frac - t_frac)) + noise;
|
|
383
|
+
check(diff, MARGIN * (noise_bound + 4.0 * E * abs(whole) + 3.0 * E * abs(noise) + 8.0 * E + CPU_REL * (f32(a_int) + abs(noise)) +
|
|
384
|
+
fpn_e_slack + det_slack));
|
|
385
|
+
var q: i32;
|
|
386
|
+
if (diff > 0.0) {
|
|
387
|
+
flags = flags | 2u;
|
|
388
|
+
q = params.sat_quantized;
|
|
389
|
+
} else {
|
|
390
|
+
|
|
391
|
+
ip = i32(params.black);
|
|
392
|
+
fp = 0.0;
|
|
393
|
+
var fpn_c_slack = 0.0;
|
|
394
|
+
if (pattern) {
|
|
395
|
+
ip = ip + bitcast<i32>(means[cursor + 2u]);
|
|
396
|
+
fp = bitcast<f32>(means[cursor + 3u]);
|
|
397
|
+
fpn_c_slack = params.fpn_c_slack;
|
|
398
|
+
}
|
|
399
399
|
scaled(a_int, ${SENSOR_AUX.inversePieces}u);
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
400
|
+
let noise_codes = noise * params.inv_gain;
|
|
401
|
+
let frac_codes = a_frac * params.inv_gain;
|
|
402
|
+
fp = fp + frac_codes + noise_codes;
|
|
403
|
+
let a_codes = f32(a_int) * params.inv_gain;
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
var margin = MARGIN * (13.0 * E * (13.0 + frac_codes + abs(noise_codes)) + 3.0 * E * frac_codes + 2.0 * E * abs(noise_codes) +
|
|
408
|
+
noise_bound * params.inv_gain + f32(a_int) * params.inv_residual +
|
|
409
|
+
CPU_REL * (a_codes + abs(noise_codes) + f32(params.black)) + fpn_c_slack + det_slack * params.inv_gain);
|
|
410
|
+
normalize();
|
|
411
|
+
if (params.knots > 0u) {
|
|
412
|
+
let ideal = f32(ip) + fp;
|
|
413
|
+
let offset = inl_offset(ideal);
|
|
414
|
+
fp = fp + offset;
|
|
415
|
+
margin = margin * (1.0 + params.inl_slope) + MARGIN * (params.inl_slope * 2.0 * E * (abs(ideal) + 1.0 + params.inl_knot) +
|
|
416
|
+
11.0 * E * (params.inl_offset + 1.0) + CPU_REL * (abs(ideal) + params.inl_offset) * (1.0 + params.inl_slope));
|
|
417
|
+
normalize();
|
|
418
|
+
}
|
|
419
|
+
if ((params.digital & 4u) == 0u) { check(fp - 0.5, margin); }
|
|
420
|
+
q = ip + select(0, 1, fp >= 0.5);
|
|
421
|
+
}
|
|
422
|
+
if ((params.digital & 1u) != 0u) {
|
|
423
|
+
let adc = clamp(q, 0, i32(params.adc_max));
|
|
424
|
+
let delta = adc - i32(params.black);
|
|
425
|
+
let estimate = f32(delta) * params.digital_gain;
|
|
426
|
+
if (estimate >= 16777216.0) {
|
|
427
|
+
q = 16777216;
|
|
428
|
+
} else if (estimate <= -16777216.0) {
|
|
429
|
+
q = -16777216;
|
|
430
|
+
} else {
|
|
431
|
+
ip = 0;
|
|
432
|
+
fp = 0.0;
|
|
433
433
|
scaled(u32(abs(delta)), ${SENSOR_AUX.digitalPieces}u);
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
if ((params.digital & 2u) == 0u) { check(fp - floor(fp) - 0.5, MARGIN * (90.0 * E + f32(abs(delta)) * params.digital_residual + CPU_REL * (abs(estimate) + f32(params.black)))); }
|
|
437
|
+
normalize();
|
|
438
|
+
var whole_part = ip;
|
|
439
|
+
var fraction = fp;
|
|
440
|
+
if (delta < 0) {
|
|
441
|
+
whole_part = -ip;
|
|
442
|
+
if (fp > 0.0) { whole_part = -ip - 1; fraction = 1.0 - fp; }
|
|
443
|
+
}
|
|
444
|
+
q = whole_part + i32(params.black) + select(0, 1, fraction >= 0.5);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
if (q >= i32(params.saturation)) { flags = flags | 4u; }
|
|
448
|
+
if (q < 0) { flags = flags | 8u; }
|
|
449
|
+
let code = u32(clamp(q, 0, i32(params.saturation)));
|
|
450
450
|
out[i] = code | (flags << 16u) | select(0u, ${1 << 20}u, uncertain);
|
|
451
451
|
}
|
|
452
452
|
`;
|