Merge branch 'histogram'
# Conflicts: # ui/dr-ui/src/lib.rs
This commit is contained in:
@@ -19,6 +19,7 @@ use std::collections::HashMap;
|
||||
use dr_pipeline::ComposedShader;
|
||||
use wgpu::util::DeviceExt;
|
||||
|
||||
use crate::readback::await_mapping;
|
||||
use crate::{DemosaicedImage, GpuContext, GpuError};
|
||||
|
||||
/// Leading floats the composer reserves before any operation's own uniforms:
|
||||
@@ -31,18 +32,6 @@ use crate::{DemosaicedImage, GpuContext, GpuError};
|
||||
/// reads them.
|
||||
const RESERVED_FIELDS: usize = dr_pipeline::RESERVED_UNIFORM_FIELDS;
|
||||
|
||||
/// How many non-blocking polls a readback gets before it is called failed.
|
||||
///
|
||||
/// A bound rather than a spin forever: if the device is lost the map callback
|
||||
/// never arrives, and an unbounded loop would hang the interface rather than
|
||||
/// surfacing the error. Set far above any plausible completion — the copy this
|
||||
/// waits on is milliseconds — so it is reached only when something is wrong.
|
||||
///
|
||||
/// Ungated along with `export_pixels`: an export reads pixels back in a
|
||||
/// shipping build, and the bound that stops a lost device hanging the app
|
||||
/// applies at least as much there as it does to the display bridge.
|
||||
const READBACK_POLL_LIMIT: u32 = 100_000;
|
||||
|
||||
/// Runs composed operation chains against demosaiced images.
|
||||
pub struct AdjustPass {
|
||||
ctx: GpuContext,
|
||||
@@ -399,38 +388,10 @@ impl AdjustPass {
|
||||
let _ = tx.send(r);
|
||||
});
|
||||
|
||||
// **Polled without blocking, then checked.**
|
||||
//
|
||||
// `Maintain::Wait` parks the calling thread until the GPU has finished,
|
||||
// and this is called from the UI thread — so that park was a frozen
|
||||
// interface for the duration of the copy (~7 ms at 4K, per the note
|
||||
// above). `Poll` drives the same callbacks without sleeping, so the
|
||||
// loop below stays interruptible and the mapping still completes.
|
||||
//
|
||||
// The bounded spin matters: a lost device would otherwise never
|
||||
// deliver the callback and this would hang the app instead of
|
||||
// reporting an error.
|
||||
let mut mapped = None;
|
||||
for _ in 0..READBACK_POLL_LIMIT {
|
||||
// A poll error is a lost device, which is exactly the case the
|
||||
// bounded spin exists to escape — returning here reports it
|
||||
// immediately rather than spinning out the full limit first.
|
||||
self.ctx
|
||||
.device
|
||||
.poll(wgpu::PollType::Poll)
|
||||
.map_err(|e| GpuError::Readback(e.to_string()))?;
|
||||
match rx.try_recv() {
|
||||
Ok(r) => {
|
||||
mapped = Some(r);
|
||||
break;
|
||||
}
|
||||
Err(std::sync::mpsc::TryRecvError::Empty) => continue,
|
||||
Err(e) => return Err(GpuError::Readback(e.to_string())),
|
||||
}
|
||||
}
|
||||
mapped
|
||||
.ok_or_else(|| GpuError::Readback("readback did not complete".into()))?
|
||||
.map_err(|e| GpuError::Readback(e.to_string()))?;
|
||||
// Polled rather than parked, and bounded rather than spun forever —
|
||||
// see `readback::await_mapping`, which the histogram's own transfer
|
||||
// shares for exactly the same reasons.
|
||||
await_mapping(&self.ctx, &rx)?;
|
||||
|
||||
let data = slice.get_mapped_range();
|
||||
let mut out = Vec::with_capacity((unpadded * h) as usize);
|
||||
|
||||
Reference in New Issue
Block a user