Commit 7af1a807d966
tarball1 file changed+36-18
@@ -12,7 +12,7 @@ use crate::format::{BYTES_PER_PIXEL, SUPPORTED};
1212
use crate::frame::{Op, VulkanFrame};1313
use crate::image::{ImageInner, VulkanImage, VulkanMapping, VulkanTarget, VulkanTexture};1414
use crate::pipeline::Pipelines;15
-use crate::staging::{Staging, StagingPool};15
+use crate::staging::{POOL_BYTES, Staging, StagingPool};1616
use crate::sync::{FenceInner, VkFence};1717
use ash::vk;1818
use gpu_allocator::MemoryLocation;@@ -63,10 +63,6 @@ struct Recorded {
6363
layouts: LayoutLog,6464
}6565
66
-/// Queued staging memory past which uploads are submitted without waiting67
-/// for a frame.68
-const UPLOAD_BATCH_BYTES: usize = 64 * 1024 * 1024;69
-7066
pub struct VulkanRenderer {7167
pending: Vec<Pending>,7268
uploads: Vec<Upload>,@@ -212,6 +208,17 @@ impl VulkanRenderer {
212208
/// Recycles finished work. A fence that cannot be queried stays213209
/// pending and fails the call, since its work may never have finished.214210
fn reap(&mut self) -> Result<(), Error> {211
+ let reaped = self.reap_fences();212
+ self.dmabuf_textures.retain(|k, _| !k.is_gone());213
+ self.dmabuf_targets.retain(|k, _| !k.is_gone());214
+ self.staged.retain(|_, (b, _)| b.is_alive());215
+ self.staging_pool.trim();216
+ reaped217
+ }218
+219
+ /// The part of `reap` that frees command buffers and staging, cheap enough220
+ /// to run for every shm commit.221
+ fn reap_fences(&mut self) -> Result<(), Error> {215222
let spare = &mut self.spare_cmds;216223
let mut failed = None;217224
self.pending.retain(|p| match p.fence.status() {@@ -225,10 +232,6 @@ impl VulkanRenderer {
225232
true226233
}227234
});228
- self.dmabuf_textures.retain(|k, _| !k.is_gone());229
- self.dmabuf_targets.retain(|k, _| !k.is_gone());230
- self.staged.retain(|_, (b, _)| b.is_alive());231
- self.staging_pool.trim();232235
failed.map_or(Ok(()), |e| Err(e.into()))233236
}234237
@@ -303,12 +306,12 @@ impl VulkanRenderer {
303306
Ok(fence)304307
}305308
306
- /// Records, submits and waits for a short command buffer. Queued uploads307
- /// go first, so `record` sees their pixels.309
+ /// Records and submits a short command buffer. Queued uploads go first, so310
+ /// `record` sees their pixels.308311
fn one_shot(309312
&mut self,310313
record: impl FnOnce(&ash::Device, vk::CommandBuffer, u32, &mut LayoutLog),311
- ) -> Result<(), Error> {314
+ ) -> Result<Arc<FenceInner>, Error> {312315
let cmd = self.begin()?;313316
let mut recorded = self.record_uploads(cmd);314317
record(@@ -317,8 +320,7 @@ impl VulkanRenderer {
317320
self.shared.device.queue_family,318321
&mut recorded.layouts,319322
);320
- let fence = self.finish(cmd, recorded, Vec::new())?;321
- Ok(fence.wait()?)323
+ self.finish(cmd, recorded, Vec::new())322324
}323325
324326
/// Submits `cmd`, which holds `recorded` and works on `keep`, and tracks@@ -406,8 +408,13 @@ impl VulkanRenderer {
406408
Recorded { uploads, layouts }407409
}408410
411
+ /// Whether pixels are staged for a frame to carry to the GPU.412
+ pub fn has_queued_uploads(&self) -> bool {413
+ !self.uploads.is_empty()414
+ }415
+409416
/// Submits the queued uploads without waiting for a frame to carry them.410
- fn flush_uploads(&mut self) -> Result<(), Error> {417
+ pub fn flush_uploads(&mut self) -> Result<(), Error> {411418
if self.uploads.is_empty() {412419
return Ok(());413420
}@@ -613,7 +620,7 @@ impl VulkanRenderer {
613620
if image.external {614621
return Err(Error::ForeignTexture);615622
}616
- self.reap()?;623
+ self.reap_fences()?;617624
if region.size.w <= 0 || region.size.h <= 0 {618625
return Ok(());619626
}@@ -653,7 +660,7 @@ impl VulkanRenderer {
653660
};654661
self.upload_bytes += upload.bytes();655662
self.uploads.push(upload);656
- if self.upload_bytes > UPLOAD_BATCH_BYTES {663
+ if self.upload_bytes >= POOL_BYTES {657664
self.flush_uploads()?;658665
}659666
Ok(())@@ -698,7 +705,7 @@ impl VulkanRenderer {
698705
});699706
let buffer = staging.buffer;700707
let source = image.clone();701
- self.one_shot(|d, cmd, family, layouts| unsafe {708
+ let fence = self.one_shot(|d, cmd, family, layouts| unsafe {702709
let mut barriers = Barriers::default();703710
barriers.acquire(704711
family,@@ -729,6 +736,17 @@ impl VulkanRenderer {
729736
&vk::DependencyInfo::default().buffer_memory_barriers(&to_host),730737
);731738
})?;739
+ if let Err(e) = fence.wait() {740
+ // A timed out GPU may still write the buffer, so it stays out of the pool.741
+ if let Some(p) = self742
+ .pending743
+ .iter_mut()744
+ .find(|p| Arc::ptr_eq(&p.fence, &fence))745
+ {746
+ p._staging.push(staging);747
+ }748
+ return Err(e.into());749
+ }732750
}733751
let mut data = staging.bytes()?[..w as usize * h as usize * BYTES_PER_PIXEL].to_vec();734752
if swap {