mirror of
https://github.com/storytold/photocraft.git
synced 2026-11-02 18:13:39 +00:00
Integration: one gpu test binary, no GPU pass for neutral settings (#6923)
- crates/gpu/tests/camera_raw.rs was its own test binary taking testkit's gpu_lock; since #8644 the crate's integration tests are one binary (tests/it) sharing crate::GPU_LOCK, so in that binary it would open a device next to the other modules. Moved into tests/it with GPU_LOCK; the testkit dev-dependency goes. - Default (neutral) settings uploaded, rendered and read back the proxy although the CPU develop returns at once. CameraRawGpu::develop now leaves them to the CPU; neutral_settings_skip_the_gpu_round_trip fails without it (backend "gpu"). - docs/hardware-parity.md: the CPU range was one backend's (21-28 ms); measured 11-16 ms on an RTX 5070 Ti, so 11-28 ms, machine-dependent. Co-authored-by: p0rps <134095787+fjamesprice@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Generated
-1
@@ -4889,7 +4889,6 @@ dependencies = [
|
||||
"photocraft-doc",
|
||||
"photocraft-geom",
|
||||
"photocraft-raster",
|
||||
"photocraft-testkit",
|
||||
"photocraft-vector",
|
||||
"pollster 1.0.1",
|
||||
"rayon",
|
||||
|
||||
@@ -32,4 +32,3 @@ pollster = "1"
|
||||
photocraft-vector = { workspace = true }
|
||||
# A document-tagged CMYK profile in the tile conversion test.
|
||||
photocraft-cms = { workspace = true }
|
||||
photocraft-testkit = { workspace = true }
|
||||
|
||||
@@ -19,7 +19,7 @@ struct Gpu {
|
||||
}
|
||||
|
||||
fn gpu() -> Option<Gpu> {
|
||||
let lock = photocraft_testkit::gpu_lock();
|
||||
let lock = crate::GPU_LOCK.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
// `WGPU_BACKEND` picks the backend; `PHOTOCRAFT_TEST_FALLBACK_ADAPTER=1` the software one (WARP).
|
||||
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor::new_without_display_handle_from_env());
|
||||
let fallback = std::env::var_os("PHOTOCRAFT_TEST_FALLBACK_ADAPTER").is_some();
|
||||
@@ -4,6 +4,7 @@
|
||||
/// creates a device takes this lock and holds it until the device is dropped.
|
||||
static GPU_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
|
||||
|
||||
mod camera_raw;
|
||||
mod device_loss;
|
||||
mod parity;
|
||||
mod timing;
|
||||
|
||||
@@ -119,9 +119,10 @@ impl CameraRawGpu {
|
||||
|
||||
/// Develops `px` (`w × h`) with `p`, or `None` when the CPU must: a spatial stage, the pass
|
||||
/// still building, a fault, or a GPU error (logged; the dialog then stays on the CPU). `key` names the pixels when they
|
||||
/// are the dialog's unchanged proxy ([`source_key`]), so they upload once.
|
||||
/// are the dialog's unchanged proxy ([`source_key`]), so they upload once. Neutral settings
|
||||
/// are `None` too: the CPU develop returns them at once, a GPU round trip would only cost.
|
||||
pub(crate) fn develop(&self, px: &[[f32; 4]], key: Option<u64>, w: usize, h: usize, p: &CameraRaw, float: bool) -> Option<Vec<[f32; 4]>> {
|
||||
if p.spatial() || self.failed.load(Ordering::Relaxed) || !self.health.is_ok() {
|
||||
if p.spatial() || p.is_identity() || self.failed.load(Ordering::Relaxed) || !self.health.is_ok() {
|
||||
return None;
|
||||
}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
@@ -264,6 +265,22 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn neutral_settings_skip_the_gpu_round_trip() {
|
||||
let _gpu = photocraft_testkit::gpu_lock();
|
||||
let Some((mut app, ctx)) = gpu_app(8) else { return };
|
||||
force_pass(&app);
|
||||
crate::camera_raw_ui::open(&mut app, &ctx).unwrap();
|
||||
if app.camera_raw.as_ref().is_some_and(|d| d.gpu.is_none()) {
|
||||
eprintln!("skipping: the device can't run the Camera Raw pass");
|
||||
return;
|
||||
}
|
||||
let (backend, _, _) = developed(&mut app, &ctx, CameraRaw { exposure: 0.5, ..Default::default() });
|
||||
assert_eq!(backend, "gpu", "a per-pixel setting develops on the GPU");
|
||||
let (backend, shown, cpu) = developed(&mut app, &ctx, CameraRaw::default());
|
||||
assert_eq!((backend, shown == cpu), ("cpu", true), "default settings: the CPU returns them unchanged");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rendering_mode_cpu_keeps_the_cpu_develop() {
|
||||
let _gpu = photocraft_testkit::gpu_lock();
|
||||
|
||||
@@ -19,7 +19,7 @@ HDR display to verify.
|
||||
|---|---|---|---|
|
||||
| GPU canvas, zoom/pan, rotate view | Metal (macOS), DirectX/OpenCL (Windows) | wgpu 30: Metal, Vulkan, DX12, GL; backend selectable | done |
|
||||
| GPU compositing of layers, blend modes, effects | partial (Photoshop composites mostly on CPU) | wgpu compositor, ≤ 1/255 vs CPU oracle; Multichannel and > texture-limit regions fall back to CPU | done (ahead in places) |
|
||||
| GPU filters (Blur Gallery, Liquify, Smart Sharpen, Camera Raw) | yes | CPU (rayon) for filters; GPU for compose and effects. Camera Raw's preview runs its per-pixel stages (white balance to grain) in one wgpu pass, 2.7 ms vs 21-28 ms on the CPU for the 858×572 proxy; spatial stages and OK still develop on the CPU (#6916) | partial |
|
||||
| GPU filters (Blur Gallery, Liquify, Smart Sharpen, Camera Raw) | yes | CPU (rayon) for filters; GPU for compose and effects. Camera Raw's preview runs its per-pixel stages (white balance to grain) in one wgpu pass, about 2-3 ms vs 11-28 ms on the CPU for the 858×572 proxy, depending on the machine; spatial stages and OK still develop on the CPU (#6916) | partial |
|
||||
| Documents larger than the GPU texture limit | yes (tiled) | CPU fallback; tiling in progress (#49) | partial |
|
||||
| CPU-only fallback when no GPU | yes, reduced | `cpu` canvas preference; fails to start without an adapter on some Linux systems (#2519, #2412) | partial |
|
||||
| Choosing the GPU on a multi-GPU machine | Preferences › Performance › Use Graphics Processor | Linux only: Preferences › Performance › Advanced › GPU adapter and `PHOTOCRAFT_GPU_ADAPTER` (#1885); ignored on Windows and macOS | partial |
|
||||
|
||||
Reference in New Issue
Block a user