render: fall back to CPU when the adapter cannot render Rgba32Float
CI / Build & test (Linux) (push) Successful in 19m8s
CI / Build & test (Windows) (push) Successful in 32m35s

This commit is contained in:
2026-08-27 13:52:03 +08:00
parent cbf9d3c543
commit f7352ae19d
+17 -3
View File
@@ -27,9 +27,11 @@
//! (the wgpu map_async callback marshalling) besides `bridge/`.
//!
//! Headless status: `GpuContext::create` requests an adapter without any
//! surface; when no adapter is available (headless CI, VMs) it returns
//! `None` and every consumer falls back to the CPU path. GPU tests skip
//! with no adapter. Verified on macOS Metal (wgpu 25.0.2).
//! surface; when no adapter is available (headless CI, VMs) or the only
//! candidates cannot render the pipeline's canonical Rgba32Float target
//! (downlevel GL/GLES), it returns `None` and every consumer falls back
//! to the CPU path. GPU tests skip with no adapter. Verified on macOS
//! Metal (wgpu 25.0.2).
use std::collections::HashMap;
use std::sync::atomic::{AtomicU64, Ordering};
@@ -221,6 +223,18 @@ impl GpuContext {
Err(_) => continue, // try the next backend in the fallback order
};
let info = adapter.get_info();
// The pipeline's canonical render target is Rgba32Float;
// adapters that cannot render it (downlevel GL/GLES without
// GL_EXT_color_buffer_float — e.g. some software Mesa
// setups) fail every pipeline/texture-usage validation, so
// treat them as unavailable and let the CPU path take over.
if !adapter
.get_texture_format_features(wgpu::TextureFormat::Rgba32Float)
.allowed_usages
.contains(wgpu::TextureUsages::RENDER_ATTACHMENT)
{
continue;
}
// Linear sampling on Rgba32Float needs FLOAT32_FILTERABLE
// (widely available on desktop GPUs); without it effect
// shaders sample nearest — a quality degradation, not a