Skip to main content

fyrox_graphics_gl/
query.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21use crate::server::GlGraphicsServer;
22use fyrox_graphics::{
23    error::FrameworkError,
24    query::{GpuQueryTrait, QueryKind, QueryResult},
25};
26use glow::HasContext;
27use std::{cell::Cell, rc::Weak};
28
29#[derive(Debug)]
30pub struct GlQuery {
31    id: glow::Query,
32    pipeline_state: Weak<GlGraphicsServer>,
33    active_query: Cell<Option<QueryKind>>,
34}
35
36impl GlQuery {
37    pub fn new(server: &GlGraphicsServer) -> Result<Self, FrameworkError> {
38        let mut inner = server.state.borrow_mut();
39        let id = if let Some(existing) = inner.queries.pop() {
40            existing
41        } else {
42            unsafe { server.gl.create_query()? }
43        };
44        Ok(Self {
45            id,
46            pipeline_state: server.weak(),
47            active_query: Default::default(),
48        })
49    }
50}
51
52impl GpuQueryTrait for GlQuery {
53    fn begin(&self, kind: QueryKind) {
54        if let Some(pipeline_state) = self.pipeline_state.upgrade() {
55            unsafe {
56                pipeline_state.gl.begin_query(kind as u32, self.id);
57            }
58
59            self.active_query.set(Some(kind));
60        }
61    }
62
63    fn end(&self) {
64        if let Some(active_query) = self.active_query.get() {
65            if let Some(pipeline_state) = self.pipeline_state.upgrade() {
66                unsafe {
67                    pipeline_state.gl.end_query(active_query as u32);
68                }
69            }
70        }
71    }
72
73    fn is_started(&self) -> bool {
74        self.active_query.get().is_some()
75    }
76
77    fn try_get_result(&self) -> Option<QueryResult> {
78        let pipeline_state = self.pipeline_state.upgrade()?;
79        let active_query = self.active_query.get()?;
80        unsafe {
81            let is_ready = pipeline_state
82                .gl
83                .get_query_parameter_u32(self.id, glow::QUERY_RESULT_AVAILABLE)
84                > 0;
85            if is_ready {
86                let query_result = pipeline_state
87                    .gl
88                    .get_query_parameter_u32(self.id, glow::QUERY_RESULT);
89                match active_query {
90                    QueryKind::SamplesPassed => Some(QueryResult::SamplesPassed(query_result)),
91                    QueryKind::AnySamplesPassed => {
92                        Some(QueryResult::AnySamplesPassed(query_result > 0))
93                    }
94                }
95            } else {
96                None
97            }
98        }
99    }
100}
101
102impl Drop for GlQuery {
103    fn drop(&mut self) {
104        if let Some(pipeline_state) = self.pipeline_state.upgrade() {
105            pipeline_state.state.borrow_mut().queries.push(self.id);
106        }
107    }
108}