Merge PR #2844: GPU: black pixels take the colour tools and a light vignette as on the CPU

This commit is contained in:
aiongg
2026-10-31 02:10:48 +00:00
2 changed files with 31 additions and 1 deletions
+3 -1
View File
@@ -106,7 +106,9 @@ fn color_ops(rgb: vec3<f32>, local_sat: f32, local_hue: f32) -> vec3<f32> {
let lab0 = oklab(rgb);
var l = lab0.x;
var c = sqrt(lab0.y * lab0.y + lab0.z * lab0.z);
var h = atan2(lab0.z, lab0.y);
// a neutral (black or grey) pixel has no hue: atan2(0, 0) is undefined in WGSL (NaN on some
// GPUs, which a later lightening such as the vignette then shows); the CPU's atan2 gives 0
var h = select(atan2(lab0.z, lab0.y), 0.0, c == 0.0);
if (pu(F_MIXER) != 0u) {
let w = band_weights(h);
var dh = 0.0;
+28
View File
@@ -494,6 +494,34 @@ fn clipped_highlights_stay_neutral_on_both() {
}
}
/// Black pixels have no hue. The GPU's `atan2(0, 0)` is undefined (NaN on some GPUs), which made
/// every exactly black pixel NaN once a colour tool ran, and a lightening vignette then showed it:
/// the CPU lifted the black corners, the GPU left them black.
#[test]
fn black_pixels_match_under_colour_tools_and_a_light_vignette() {
if !gpu() {
return;
}
let base = scene(0, 320, 240);
// black bars across the frame, reaching into the corners the vignette lightens
let src = Arc::new(Rgb32f::from_fn(320, 240, |x, y| if y % 40 < 8 || x % 64 < 6 { [0.0; 3] } else { base.get(x, y) }));
let info = SourceInfo { raw: true, ..Default::default() };
let req = RenderRequest::fit(320, 240);
for (name, f) in [
("black, light vignette + saturation", (|s: &mut DevelopSettings| s.color.saturation = 40.0) as fn(&mut DevelopSettings)),
("black, light vignette + vibrance", |s| s.color.vibrance = 30.0),
("black, light vignette + mixer", |s| s.mixer.yellow.hue = 30.0),
] {
let mut s = DevelopSettings::default();
s.vignette.amount = 25.0;
s.vignette.style = VignetteStyle::HighlightPriority;
f(&mut s);
check(name, &src, &info, &s, &req);
let gpu = lightcraft_gpu::render(&src, &info, &s, &req, None).expect("gpu render").image;
assert!(gpu.get(0, 0)[1] > 0, "{name}: the black corner is not lightened on the GPU");
}
}
#[test]
fn rendered_sources_and_other_scenes() {
if !gpu() {