fyrox_graphics/
query.rs

1//! A query object is used to fetch some data from rendering operations asynchronously. See
2//! [`GpuQueryTrait`] docs for more info.
3
4#![warn(missing_docs)]
5
6use crate::core::Downcast;
7use crate::define_shared_wrapper;
8use std::fmt::Debug;
9
10/// Kind of a GPU query.
11#[repr(u32)]
12#[derive(Copy, Clone, Debug)]
13pub enum QueryKind {
14    /// Queries a number of rendered pixels; any pixel that passed all pipeline tests counts.
15    SamplesPassed = glow::SAMPLES_PASSED,
16
17    /// Queries a flag that defines whether the rendering operation produced any pixels or not.
18    AnySamplesPassed = glow::ANY_SAMPLES_PASSED,
19}
20
21/// Result of a query.
22#[derive(Debug)]
23pub enum QueryResult {
24    /// Number of rendered pixels; any pixel that passed all pipeline tests counts.
25    SamplesPassed(u32),
26
27    /// A flag that defines whether the rendering operation produced any pixels or not.
28    AnySamplesPassed(bool),
29}
30
31/// A query object is used to fetch some data from rendering operations asynchronously. Usually it
32/// is used to perform occlusion queries.
33///
34/// ## Examples
35///
36/// The following examples shows how to create a new GPU query, run it and fetch the result.
37///
38/// ```rust
39/// use fyrox_graphics::{
40///     error::FrameworkError,
41///     query::{QueryKind, QueryResult},
42///     server::GraphicsServer,
43/// };
44///
45/// fn query(server: &dyn GraphicsServer) -> Result<(), FrameworkError> {
46///     // Initialization.
47///     let query = server.create_query()?;
48///
49///     // Somewhere in the rendering loop.
50///     if !query.is_started() {
51///         query.begin(QueryKind::AnySamplesPassed);
52///
53///         // Draw something.
54///
55///         query.end();
56///     } else if let Some(QueryResult::AnySamplesPassed(any_samples_passed)) =
57///         query.try_get_result()
58///     {
59///         println!("{any_samples_passed}");
60///     }
61///
62///     Ok(())
63/// }
64/// ```
65///
66/// Keep in mind that you should always re-use the queries instead of creating them on the fly!
67/// This is much more efficient, because it removes all redundant memory allocations and calls
68/// to the GPU driver.
69pub trait GpuQueryTrait: Downcast + Debug {
70    /// Begins a query of the given kind. All drawing commands must be enclosed withing a pair of
71    /// this method and [`Self::end`] calls. See [`QueryKind`] for more info.
72    fn begin(&self, kind: QueryKind);
73
74    /// Ends the query. Must be called after and in pair with [`Self::begin`].
75    fn end(&self);
76
77    /// Returns `true` if the query is started ([`Self::begin`] was called).
78    fn is_started(&self) -> bool;
79
80    /// Tries to fetch the query result without blocking. The query object guarantees that the
81    /// result will be stored until the next call of [`Self::begin`], so consecutive calls of this
82    /// method are allowed.
83    fn try_get_result(&self) -> Option<QueryResult>;
84}
85
86define_shared_wrapper!(GpuQuery<dyn GpuQueryTrait>);