1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
use {
clap::Parser,
screen_13::prelude::*,
std::{sync::Arc, time::Instant},
};
/// Example demonstrating the steps to take when reading the results of buffer or image operations
/// on the CPU. These operations take time to submit and the GPU will execute them asynchronously.
fn main() -> Result<(), DriverError> {
pretty_env_logger::init();
// For this example we create a headless device, but the same thing works using a window
let args = Args::parse();
let device_info = DeviceInfoBuilder::default().debug(args.debug);
let device = Arc::new(Device::create_headless(device_info)?);
let mut render_graph = RenderGraph::new();
let src_buf = render_graph.bind_node(Buffer::create_from_slice(
&device,
vk::BufferUsageFlags::TRANSFER_SRC,
[1, 2, 3, 4],
)?);
let dst_buf = render_graph.bind_node(Buffer::create_from_slice(
&device,
vk::BufferUsageFlags::TRANSFER_DST,
[0, 0, 0, 0],
)?);
// We are using the GPU to copy data, but the same thing works if you're executing a pipeline
// such as a ComputePipeline to run some shader code which writes to a buffer or image. It is
// important to note that dst_buf does not contain the new data until we submit this render
// graph and wait on the result
render_graph.copy_buffer(src_buf, dst_buf);
// This line is optional - just bind a reference of Arc<Buffer> or a leased buffer so you retain
// the actual buffer for later use and you could then remove this unbind_node line
let dst_buf = render_graph.unbind_node(dst_buf);
// Resolve and wait (or you can check has_executed without blocking) - alternatively you might
// use device.queue_wait_idle(0) or device.device_wait_idle() - but those block on larger scopes
let mut cmd_buf = render_graph
.resolve()
.submit(&mut HashPool::new(&device), 0, 0)?;
println!("Has executed? {}", cmd_buf.has_executed()?);
let started = Instant::now();
cmd_buf.wait_until_executed()?;
assert!(
cmd_buf.has_executed()?,
"We checked above - so this will always be true"
);
println!("Waited {}μs", (Instant::now() - started).as_micros());
// It is now safe to read back what we did!
println!("{:?}", Buffer::mapped_slice(&dst_buf));
Ok(())
}
#[derive(Parser)]
struct Args {
/// Enable Vulkan SDK validation layers
#[arg(long)]
debug: bool,
}