Skip to main content

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