xref: /aosp_15_r20/external/mesa3d/src/gallium/frontends/rusticl/mesa/pipe/query.rs (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 use crate::pipe::context::*;
2 
3 use mesa_rust_gen::*;
4 
5 use std::marker::*;
6 
7 // Callers create new queries using PipeQueryGen<QueryType>::new(...)
8 pub struct PipeQueryGen<const Q: pipe_query_type::Type> {}
9 
10 // We record the type that the given Query type will return into
11 // a trait we associate with a PipeQuery object we return
12 // QueryResultTrait is the type we'd like our PipeQueryGen to return
13 // for a given query
14 pub trait QueryResultTrait {
15     type ResType;
16 }
17 
18 // Define this set of PipeQueryGen's for these queries
19 impl QueryResultTrait for PipeQueryGen<{ pipe_query_type::PIPE_QUERY_TIMESTAMP }> {
20     type ResType = u64;
21 }
22 
23 impl<const Q: pipe_query_type::Type> PipeQueryGen<Q>
24 where
25     PipeQueryGen<Q>: QueryResultTrait,
26 {
27     // The external interface to create a new query
new(ctx: &PipeContext) -> Option<PipeQuery<<Self as QueryResultTrait>::ResType>>28     pub fn new(ctx: &PipeContext) -> Option<PipeQuery<<Self as QueryResultTrait>::ResType>> {
29         PipeQuery::<<Self as QueryResultTrait>::ResType>::new(ctx, Q)
30     }
31 }
32 
33 // Our higher level view of a 'pipe_query', created by a call to the
34 // 'create_query' method on the pipe context
35 pub struct PipeQuery<'a, R> {
36     query: *mut pipe_query,
37     ctx: &'a PipeContext,
38 
39     _result_marker: PhantomData<R>,
40 }
41 
42 impl<'a, R> PipeQuery<'a, R> {
new(ctx: &'a PipeContext, query_type: u32) -> Option<Self>43     fn new(ctx: &'a PipeContext, query_type: u32) -> Option<Self> {
44         let pq = ctx.create_query(query_type, 0);
45         if pq.is_null() {
46             return None;
47         }
48         // SAFETY: we are the only owner of that valid pointer
49         unsafe {
50             if !ctx.end_query(pq) {
51                 ctx.destroy_query(pq);
52                 return None;
53             }
54         }
55         Some(Self {
56             query: pq,
57             ctx: ctx,
58             _result_marker: Default::default(),
59         })
60     }
61 }
62 
63 impl<'a, R> Drop for PipeQuery<'a, R> {
drop(&mut self)64     fn drop(&mut self) {
65         // SAFETY: we are the only owner of that valid pointer
66         unsafe {
67             self.ctx.destroy_query(self.query);
68         }
69     }
70 }
71 
72 pub trait QueryReadTrait {
73     type ResType;
read(&mut self, wait: bool) -> Option<Self::ResType>74     fn read(&mut self, wait: bool) -> Option<Self::ResType>;
75 
read_blocked(&mut self) -> Self::ResType76     fn read_blocked(&mut self) -> Self::ResType {
77         self.read(true).unwrap()
78     }
79 }
80 
81 impl QueryReadTrait for PipeQuery<'_, u64> {
82     type ResType = u64;
83 
read(&mut self, wait: bool) -> Option<u64>84     fn read(&mut self, wait: bool) -> Option<u64> {
85         let mut raw_result = pipe_query_result::default();
86         // SAFETY: we guarentee unique access through our `&mut self` reference above.
87         if unsafe { self.ctx.get_query_result(self.query, wait, &mut raw_result) } {
88             // SAFETY: We know this is the right type
89             // because of the trait bound on PipeQueryGen binds the
90             // query type with the result type.
91             Some(unsafe { raw_result.u64_ })
92         } else {
93             None
94         }
95     }
96 }
97