molgfx_gpu/queue.rs
1//! The submission queue trait.
2
3use crate::device::Device;
4use crate::error::GpuError;
5use crate::{FenceValue, TextureWrite};
6use std::future::Future;
7
8/// A detached readback over one buffer.
9///
10/// The handle owns everything it needs to await a mapped range, so a caller
11/// can release every borrow of the renderer that submitted the copy before
12/// the wait begins. On the browser's single JavaScript thread that is what
13/// lets a frame render while a pick is still resolving its readback.
14pub trait Readback: std::fmt::Debug {
15 /// Awaits the mapped range and returns its bytes.
16 ///
17 /// # Errors
18 ///
19 /// The device was lost, or the buffer was not readable.
20 fn resolve(
21 &self,
22 offset: u64,
23 size: u64,
24 ) -> impl Future<Output = Result<Vec<u8>, GpuError>> + '_;
25
26 /// Copies a mapped range into caller-owned scratch without allocating bytes.
27 /// Only the first `size` bytes are written; the remaining output is unchanged.
28 /// The future borrows this detached handle and the scratch, not the renderer.
29 ///
30 /// # Errors
31 /// Returns device or mapping errors, or an invalid, unaligned, overflowing
32 /// range or output shorter than `size`, before writing any output.
33 fn resolve_into<'a>(
34 &'a self,
35 offset: u64,
36 size: u64,
37 output: &'a mut [u8],
38 ) -> impl Future<Output = Result<(), GpuError>> + 'a;
39}
40
41/// Uploads and submission. One submission per frame is the discipline the
42/// engine holds; the trait does not enforce it, the render loop does.
43pub trait Queue<D: Device> {
44 /// Writes bytes into a buffer at an offset. The source is borrowed for
45 /// the duration of the call — an upload from a caller's slice is
46 /// copy-free on the host side.
47 fn write_buffer(&self, buffer: &D::Buffer, offset: u64, data: &[u8]);
48
49 /// Uploads a borrowed, tightly described region into a texture.
50 fn write_texture(&self, texture: &D::Texture, write: &TextureWrite<'_>);
51
52 /// Submits one encoder's recorded work.
53 fn submit(&self, encoder: D::CommandEncoder);
54
55 /// Submits work whose completion must gate resource residency.
56 fn submit_tracked(&self, encoder: D::CommandEncoder) -> FenceValue;
57
58 /// Polls the backend and returns the greatest submission known complete.
59 ///
60 /// # Errors
61 ///
62 /// Returns device loss when completion status can no longer be queried.
63 fn completed_fence(&self, device: &D) -> Result<FenceValue, GpuError>;
64
65 /// Awaits a tracked submission without mapping a pixel or timestamp buffer.
66 ///
67 /// # Errors
68 /// Returns device loss or a failed completion observation.
69 fn wait_fence<'a>(
70 &'a self,
71 device: &'a D,
72 fence: FenceValue,
73 ) -> impl Future<Output = Result<(), GpuError>> + 'a;
74
75 /// Native blocking completion wait, without readback.
76 ///
77 /// # Errors
78 /// Returns device loss or a failed completion observation.
79 #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
80 fn wait_fence_blocking(&self, device: &D, fence: FenceValue) -> Result<(), GpuError>;
81
82 /// Resolves a mapped buffer range without blocking the browser event loop.
83 /// Off the frame path only: golden-image capture, picking and export.
84 ///
85 /// # Errors
86 ///
87 /// The device was lost, or the buffer was not readable.
88 fn read_buffer_async<'a>(
89 &'a self,
90 device: &'a D,
91 buffer: &'a D::Buffer,
92 offset: u64,
93 size: u64,
94 ) -> impl Future<Output = Result<Vec<u8>, GpuError>> + 'a;
95
96 /// Resolves a buffer range into reserved host scratch without allocating bytes.
97 /// Only the first `size` bytes are written; the remaining output is unchanged.
98 ///
99 /// # Errors
100 /// Returns the same errors as [`Readback::resolve_into`].
101 fn read_buffer_into_async<'a>(
102 &'a self,
103 device: &'a D,
104 buffer: &'a D::Buffer,
105 offset: u64,
106 size: u64,
107 output: &'a mut [u8],
108 ) -> impl Future<Output = Result<(), GpuError>> + 'a;
109
110 /// Detaches a readback handle over one buffer.
111 ///
112 /// The returned handle borrows nothing, so the caller is free to use the
113 /// device and queue while a [`Readback::resolve`] is still awaiting.
114 fn readback(&self, device: &D, buffer: &D::Buffer) -> D::Readback;
115
116 /// Native convenience that waits for a mapped range. Browser callers use
117 /// [`Self::read_buffer_async`].
118 ///
119 /// # Errors
120 ///
121 /// The device was lost, or the buffer was not readable.
122 #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
123 fn read_buffer_blocking(
124 &self,
125 device: &D,
126 buffer: &D::Buffer,
127 offset: u64,
128 size: u64,
129 ) -> Result<Vec<u8>, GpuError>;
130
131 /// Native blocking read into reserved host scratch.
132 ///
133 /// # Errors
134 /// Returns the same errors as [`Readback::resolve_into`].
135 #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
136 fn read_buffer_into_blocking(
137 &self,
138 device: &D,
139 buffer: &D::Buffer,
140 offset: u64,
141 size: u64,
142 output: &mut [u8],
143 ) -> Result<(), GpuError>;
144
145 /// Nanoseconds represented by one timestamp-query tick.
146 fn timestamp_period(&self) -> f32;
147}