Skip to main content

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    /// Requests a map of one range and returns at once.
41    ///
42    /// The map completes as the device is polled. One request is outstanding
43    /// per handle, so a ring reuses its handles and allocates nothing per
44    /// request; pair every call with [`Self::try_finish_into`].
45    ///
46    /// # Errors
47    /// Returns an invalid, unaligned or overflowing range, an unreadable
48    /// buffer, or a request already outstanding on this handle.
49    fn begin_map(&self, offset: u64, size: u64) -> Result<(), GpuError>;
50
51    /// Copies the requested range into `output` and unmaps once the map
52    /// completed. Returns `Ok(false)` while it is still pending; never blocks.
53    ///
54    /// # Errors
55    /// Returns device or mapping errors, no request outstanding, or an output
56    /// shorter than the requested range.
57    fn try_finish_into(&self, output: &mut [u8]) -> Result<bool, GpuError>;
58}
59
60/// Uploads and submission. One submission per frame is the discipline the
61/// engine holds; the trait does not enforce it, the render loop does.
62pub trait Queue<D: Device> {
63    /// Writes bytes into a buffer at an offset. The source is borrowed for
64    /// the duration of the call — an upload from a caller's slice is
65    /// copy-free on the host side.
66    fn write_buffer(&self, buffer: &D::Buffer, offset: u64, data: &[u8]);
67
68    /// Uploads a borrowed, tightly described region into a texture.
69    fn write_texture(&self, texture: &D::Texture, write: &TextureWrite<'_>);
70
71    /// Submits one encoder's recorded work.
72    fn submit(&self, encoder: D::CommandEncoder);
73
74    /// Submits work whose completion must gate resource residency.
75    fn submit_tracked(&self, encoder: D::CommandEncoder) -> FenceValue;
76
77    /// Polls the backend and returns the greatest submission known complete.
78    ///
79    /// # Errors
80    ///
81    /// Returns device loss when completion status can no longer be queried.
82    fn completed_fence(&self, device: &D) -> Result<FenceValue, GpuError>;
83
84    /// Awaits a tracked submission without mapping a pixel or timestamp buffer.
85    ///
86    /// # Errors
87    /// Returns device loss or a failed completion observation.
88    fn wait_fence<'a>(
89        &'a self,
90        device: &'a D,
91        fence: FenceValue,
92    ) -> impl Future<Output = Result<(), GpuError>> + 'a;
93
94    /// Native blocking completion wait, without readback.
95    ///
96    /// # Errors
97    /// Returns device loss or a failed completion observation.
98    #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
99    fn wait_fence_blocking(&self, device: &D, fence: FenceValue) -> Result<(), GpuError>;
100
101    /// Resolves a mapped buffer range without blocking the browser event loop.
102    /// Off the frame path only: golden-image capture, picking and export.
103    ///
104    /// # Errors
105    ///
106    /// The device was lost, or the buffer was not readable.
107    fn read_buffer_async<'a>(
108        &'a self,
109        device: &'a D,
110        buffer: &'a D::Buffer,
111        offset: u64,
112        size: u64,
113    ) -> impl Future<Output = Result<Vec<u8>, GpuError>> + 'a;
114
115    /// Resolves a buffer range into reserved host scratch without allocating bytes.
116    /// Only the first `size` bytes are written; the remaining output is unchanged.
117    ///
118    /// # Errors
119    /// Returns the same errors as [`Readback::resolve_into`].
120    fn read_buffer_into_async<'a>(
121        &'a self,
122        device: &'a D,
123        buffer: &'a D::Buffer,
124        offset: u64,
125        size: u64,
126        output: &'a mut [u8],
127    ) -> impl Future<Output = Result<(), GpuError>> + 'a;
128
129    /// Detaches a readback handle over one buffer.
130    ///
131    /// The returned handle borrows nothing, so the caller is free to use the
132    /// device and queue while a [`Readback::resolve`] is still awaiting.
133    fn readback(&self, device: &D, buffer: &D::Buffer) -> D::Readback;
134
135    /// Native convenience that waits for a mapped range. Browser callers use
136    /// [`Self::read_buffer_async`].
137    ///
138    /// # Errors
139    ///
140    /// The device was lost, or the buffer was not readable.
141    #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
142    fn read_buffer_blocking(
143        &self,
144        device: &D,
145        buffer: &D::Buffer,
146        offset: u64,
147        size: u64,
148    ) -> Result<Vec<u8>, GpuError>;
149
150    /// Native blocking read into reserved host scratch.
151    ///
152    /// # Errors
153    /// Returns the same errors as [`Readback::resolve_into`].
154    #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
155    fn read_buffer_into_blocking(
156        &self,
157        device: &D,
158        buffer: &D::Buffer,
159        offset: u64,
160        size: u64,
161        output: &mut [u8],
162    ) -> Result<(), GpuError>;
163
164    /// Nanoseconds represented by one timestamp-query tick.
165    fn timestamp_period(&self) -> f32;
166}