ci: prove the lavapipe GPU path draws (FIELDCRAFT_REQUIRE_GPU=1)

The drawing tests skipped silently without an adapter. Under
FIELDCRAFT_REQUIRE_GPU=1 they fail instead, and the snapshot and MCP
screenshot tests require a GPU renderer. CI runs them with
FIELDCRAFT_GPU=software on lavapipe.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
This commit is contained in:
jyvikoandClaude Opus 5.5 authored and Irakli Kourtis committed 2026-10-16 07:52:10 -04:00
1 parent b905f1bc89
commit c6bc4d2ba0
5 files changed
+24 -5

No files matched your search

+5 -3
View File
@@ -304,12 +304,14 @@ mod tests {
}
/// A picture on whatever adapter the machine has: the right size, the triangle's red and
/// the edge's black on the white background. A machine with no adapter (a CI box without
/// a software GPU) is reported, not failed: `auto` then draws on the CPU.
/// the edge's black on the white background. A machine with no adapter is reported, not
/// failed (`auto` then draws on the CPU), unless `FIELDCRAFT_REQUIRE_GPU=1` (CI).
#[test]
fn draws_offscreen_when_an_adapter_exists() {
let cap = match Capturer::open(Policy::Auto) {
let cap = match Capturer::open(Policy::from_env().unwrap()) {
Ok(Some(c)) => c,
Ok(None) if crate::select::gpu_required() => panic!("FIELDCRAFT_REQUIRE_GPU=1 but no GPU adapter"),
Err(e) if crate::select::gpu_required() => panic!("FIELDCRAFT_REQUIRE_GPU=1 but no GPU device: {e}"),
Ok(None) => return eprintln!("no GPU adapter: skipped"),
Err(e) => return eprintln!("no GPU device ({e}): skipped"),
};
+9
View File
@@ -46,6 +46,15 @@ impl Policy {
pub use crate::Tier;
/// Set to `1` where a GPU adapter must exist (CI with lavapipe): tests that draw then fail
/// instead of skipping when none is found, so the GPU path is proven to draw.
pub const REQUIRE_ENV: &str = "FIELDCRAFT_REQUIRE_GPU";
/// Whether [`REQUIRE_ENV`] is set to `1`.
pub fn gpu_required() -> bool {
std::env::var(REQUIRE_ENV).is_ok_and(|v| v.trim() == "1")
}
/// An adapter's tier and its rank within it (lower is better).
pub fn rank(t: wgpu::DeviceType) -> (Tier, u8) {
match t {
+3
View File
@@ -222,6 +222,9 @@ fn screenshot_takes_a_camera_orientation() {
assert_eq!(info["view"], json!({"yaw": 30.0, "pitch": 90.0, "distance": 1e9, "target": {"center_of": "mass"}}), "{info}");
// The reply names what drew it: the viewport's pipeline on a GPU, or the CPU rasterizer.
assert!(matches!(info["renderer"]["kind"].as_str(), Some("hardware" | "software" | "cpu")), "{info}");
if fieldcraft_gpu::select::gpu_required() {
assert!(matches!(info["renderer"]["kind"].as_str(), Some("hardware" | "software")), "FIELDCRAFT_REQUIRE_GPU=1: {info}");
}
let (again, _) = picture(&mut s, json!({"width": 64, "height": 48}));
assert_eq!(again, turned);
// Aimed at a point, the camera looks at it; a section cuts the mesh.