fix(macos): gate real GL for the whole test build; add Windows diagnostics
- The macOS SIGSEGV moved from the gl_bridge unit tests (already gated) to other real-GL users in the same binary (suites::gl_render, render_driver): make the gate systemic in the test build on macOS. gl_available() reports unavailable and acquire() fails unless OAK_GPU_TESTS is set, so every unit test takes its documented CPU fallback; release builds are untouched. - Dump Apple's crash reports on macOS failure: a SIGSEGV in a test binary prints nothing, and the .ips report carries the native stack. - The Windows-only multicam graph test failure now prints both decoded media probes and both rendered source pixels: that separates a broken test-media encode from a broken graph switch in one run.
This commit is contained in:
@@ -505,6 +505,17 @@ jobs:
|
|||||||
cargo test --workspace --locked
|
cargo test --workspace --locked
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# A SIGSEGV in a test binary gives no Rust backtrace; Apple's crash
|
||||||
|
# reports carry the native stack, so surface the newest ones.
|
||||||
|
- name: Crash reports
|
||||||
|
if: failure()
|
||||||
|
run: |
|
||||||
|
for f in $(ls -t ~/Library/Logs/DiagnosticReports/*.ips 2>/dev/null | head -3); do
|
||||||
|
echo "===== $f"
|
||||||
|
head -c 6000 "$f"
|
||||||
|
echo
|
||||||
|
done
|
||||||
|
|
||||||
# second upstream target: openKylin (Debian/Ubuntu-derived) in its own
|
# second upstream target: openKylin (Debian/Ubuntu-derived) in its own
|
||||||
# image. The base image is bare (no sudo, no make, no python3) and the
|
# image. The base image is bare (no sudo, no make, no python3) and the
|
||||||
# steps run as root, so there is no sudo prefix anywhere below.
|
# steps run as root, so there is no sudo prefix anywhere below.
|
||||||
|
|||||||
@@ -2500,6 +2500,32 @@ mod tests {
|
|||||||
oak_codec::testmedia::write_test_clip_solid(&blue, 64, 64, 10, 10, [0.0, 0.0, 1.0, 1.0])
|
oak_codec::testmedia::write_test_clip_solid(&blue, 64, 64, 10, 10, [0.0, 0.0, 1.0, 1.0])
|
||||||
.expect("blue angle");
|
.expect("blue angle");
|
||||||
|
|
||||||
|
// Diagnostic (the Windows-only switch failure): decode each file
|
||||||
|
// directly, so a red-ish source 1 can be blamed on the generated
|
||||||
|
// media or on the graph.
|
||||||
|
let probe = |name: &str, path: &std::path::Path| -> (f32, f32) {
|
||||||
|
let texture = oak_render::eval::render_footage_frame(
|
||||||
|
&path.to_string_lossy(),
|
||||||
|
0,
|
||||||
|
oak_core::Rational::new(0, 1),
|
||||||
|
(64, 64),
|
||||||
|
oak_core::PixelFormat::F32,
|
||||||
|
)
|
||||||
|
.unwrap_or_else(|e| panic!("probe {name}: {e}"));
|
||||||
|
let frame = texture.to_frame().expect("probe readback");
|
||||||
|
let stride = frame.linesize_bytes() as usize;
|
||||||
|
let off = 8 * stride + 8 * 16;
|
||||||
|
(
|
||||||
|
f32::from_le_bytes(frame.data[off..off + 4].try_into().unwrap()),
|
||||||
|
f32::from_le_bytes(frame.data[off + 8..off + 12].try_into().unwrap()),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
println!(
|
||||||
|
"multicam media probe: red={:?} blue={:?}",
|
||||||
|
probe("red", &red),
|
||||||
|
probe("blue", &blue)
|
||||||
|
);
|
||||||
|
|
||||||
let (project, seq, _rfoot) = project_with_clip(&red);
|
let (project, seq, _rfoot) = project_with_clip(&red);
|
||||||
let bfoot = graphops::import_footage(&project, &blue).expect("import blue");
|
let bfoot = graphops::import_footage(&project, &blue).expect("import blue");
|
||||||
graphops::add_track(&project, seq, TrackType::Video).expect("track 1");
|
graphops::add_track(&project, seq, TrackType::Video).expect("track 1");
|
||||||
@@ -2623,6 +2649,12 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let (r1, b1) = render_rgb(0);
|
let (r1, b1) = render_rgb(0);
|
||||||
|
// Diagnostic on failure: identical pairs mean the second render was
|
||||||
|
// served the first frame; a red-ish source 1 means the selected
|
||||||
|
// element resolved wrong.
|
||||||
|
println!(
|
||||||
|
"multicam graph render: source 0 -> (r={r0:.4}, b={b0:.4}), source 1 -> (r={r1:.4}, b={b1:.4})"
|
||||||
|
);
|
||||||
assert!(
|
assert!(
|
||||||
b1 > 0.4 && r1 < 0.4,
|
b1 > 0.4 && r1 < 0.4,
|
||||||
"source 1 switches the node-graph frame to blue (r={r1} b={b1})"
|
"source 1 switches the node-graph frame to blue (r={r1} b={b1})"
|
||||||
|
|||||||
@@ -88,10 +88,24 @@ use crate::render::VideoParams;
|
|||||||
|
|
||||||
// ---- 对外 API(平台无关签名;实现按平台 cfg 分派)----------------------
|
// ---- 对外 API(平台无关签名;实现按平台 cfg 分派)----------------------
|
||||||
|
|
||||||
|
/// Whether the TEST build may touch the real CGL context on macOS. The
|
||||||
|
/// headless CI runner cannot exercise Apple's GL reliably (parallel unit
|
||||||
|
/// tests have segfaulted inside the driver), so the test build behaves as
|
||||||
|
/// if GL were unavailable unless `OAK_GPU_TESTS` asks for it — the same
|
||||||
|
/// gate the integration GL tests use. Release builds are untouched.
|
||||||
|
#[cfg(all(test, target_os = "macos"))]
|
||||||
|
fn real_gl_gated() -> bool {
|
||||||
|
std::env::var_os("OAK_GPU_TESTS").is_none()
|
||||||
|
}
|
||||||
|
|
||||||
/// GL 上下文是否可用(离屏上下文可创建)。use_opengl 决策用它当
|
/// GL 上下文是否可用(离屏上下文可创建)。use_opengl 决策用它当
|
||||||
/// "目标纹理有有效 GL 名" 的门:桥能为目标帧建出真实 GL 纹理 ⟺
|
/// "目标纹理有有效 GL 名" 的门:桥能为目标帧建出真实 GL 纹理 ⟺
|
||||||
/// 上下文可用。惰性创建,幂等。
|
/// 上下文可用。惰性创建,幂等。
|
||||||
pub fn gl_available() -> bool {
|
pub fn gl_available() -> bool {
|
||||||
|
#[cfg(all(test, target_os = "macos"))]
|
||||||
|
if real_gl_gated() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
imp::gl_available()
|
imp::gl_available()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,6 +113,12 @@ pub fn gl_available() -> bool {
|
|||||||
/// 返回的 guard 在 drop 时清 current 并放锁。失败(无 GL / 上下文
|
/// 返回的 guard 在 drop 时清 current 并放锁。失败(无 GL / 上下文
|
||||||
/// 创建失败)→ 调用方回退 CPU。
|
/// 创建失败)→ 调用方回退 CPU。
|
||||||
pub fn acquire() -> crate::error::Result<GlGuard> {
|
pub fn acquire() -> crate::error::Result<GlGuard> {
|
||||||
|
#[cfg(all(test, target_os = "macos"))]
|
||||||
|
if real_gl_gated() {
|
||||||
|
return Err(crate::error::Error::Failed(
|
||||||
|
"gl_bridge: real GL is gated behind OAK_GPU_TESTS in tests".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
imp::acquire()
|
imp::acquire()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user