aboutsummaryrefslogtreecommitdiff
path: root/adapters/fparkan-render-vulkan/src/ffi/smoke.rs
diff options
context:
space:
mode:
Diffstat (limited to 'adapters/fparkan-render-vulkan/src/ffi/smoke.rs')
-rw-r--r--adapters/fparkan-render-vulkan/src/ffi/smoke.rs47
1 files changed, 38 insertions, 9 deletions
diff --git a/adapters/fparkan-render-vulkan/src/ffi/smoke.rs b/adapters/fparkan-render-vulkan/src/ffi/smoke.rs
index f7c72b6..e41f0f9 100644
--- a/adapters/fparkan-render-vulkan/src/ffi/smoke.rs
+++ b/adapters/fparkan-render-vulkan/src/ffi/smoke.rs
@@ -235,6 +235,7 @@ impl VulkanSmokeRenderer {
frame_sync: Vec::new(),
images_in_flight: Vec::new(),
current_frame: 0,
+ last_readback_image_index: None,
depth_request: create_info.render_request.depth,
pending_extent: None,
swapchain_recreate_count: 0,
@@ -519,6 +520,7 @@ impl VulkanSmokeRenderer {
})?;
if !self.resources_ref()?.readback_buffers.is_empty() {
self.report.readback_copy_count = self.report.readback_copy_count.saturating_add(1);
+ self.last_readback_image_index = Some(image_index_usize);
}
let present_wait = [render_finished];
@@ -621,6 +623,7 @@ impl VulkanSmokeRenderer {
let resources = resources.commit();
self.images_in_flight = vec![vk::Fence::null(); resources.image_views.len()];
self.frame_sync = frame_sync;
+ self.last_readback_image_index = None;
self.report.swapchain_extent = swapchain_extent;
self.report.swapchain_image_count = swapchain_image_count;
self.report.swapchain_image_format = self.swapchain_ref()?.report.plan.format.format;
@@ -941,13 +944,19 @@ impl VulkanSmokeRenderer {
if resources.readback_buffers.is_empty() {
return Ok(None);
}
- let mut artifact =
- Vec::with_capacity(byte_len.saturating_mul(resources.readback_buffers.len()));
- for buffer in &resources.readback_buffers {
- let bytes = readback_buffer_bytes(device, buffer, byte_len)?;
- artifact.extend_from_slice(&bytes);
- }
- Ok(Some(artifact))
+ let Some(image_index) = completed_readback_buffer_index(
+ self.last_readback_image_index,
+ resources.readback_buffers.len(),
+ )?
+ else {
+ return Ok(None);
+ };
+ let buffer = resources.readback_buffers.get(image_index).ok_or(
+ VulkanSmokeRendererError::InvariantViolation {
+ context: "last readback image index",
+ },
+ )?;
+ Ok(Some(readback_buffer_bytes(device, buffer, byte_len)?))
}
fn teardown(&mut self) {
@@ -968,6 +977,19 @@ impl VulkanSmokeRenderer {
}
}
+fn completed_readback_buffer_index(
+ last_image_index: Option<usize>,
+ buffer_count: usize,
+) -> Result<Option<usize>, VulkanSmokeRendererError> {
+ match last_image_index {
+ None => Ok(None),
+ Some(index) if index < buffer_count => Ok(Some(index)),
+ Some(_) => Err(VulkanSmokeRendererError::InvariantViolation {
+ context: "last readback image index",
+ }),
+ }
+}
+
fn matrix_bytes(matrix: [f32; 16]) -> [u8; 64] {
let mut bytes = [0; 64];
for (index, value) in matrix.into_iter().enumerate() {
@@ -991,8 +1013,8 @@ impl Drop for VulkanSmokeRenderer {
#[cfg(test)]
mod tests {
use super::{
- take_runtime_children_with_validation_snapshot, take_runtime_owners_in_dependency_order,
- RollbackOnDrop,
+ completed_readback_buffer_index, take_runtime_children_with_validation_snapshot,
+ take_runtime_owners_in_dependency_order, RollbackOnDrop,
};
use std::cell::RefCell;
use std::rc::Rc;
@@ -1076,6 +1098,13 @@ mod tests {
}
#[test]
+ fn completed_readback_selects_only_the_last_submitted_image() {
+ assert_eq!(completed_readback_buffer_index(None, 2), Ok(None));
+ assert_eq!(completed_readback_buffer_index(Some(1), 2), Ok(Some(1)));
+ assert!(completed_readback_buffer_index(Some(2), 2).is_err());
+ }
+
+ #[test]
fn runtime_owners_drop_remaining_children_after_partial_init_failures() {
let cases = [
(vec![TeardownStep::Instance], vec![TeardownStep::Instance]),