xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/r300/r300_query.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2009 Corbin Simpson <[email protected]>
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "util/u_memory.h"
7 
8 #include "r300_context.h"
9 #include "r300_screen.h"
10 #include "r300_emit.h"
11 
12 #include <stdio.h>
13 
r300_create_query(struct pipe_context * pipe,unsigned query_type,unsigned index)14 static struct pipe_query *r300_create_query(struct pipe_context *pipe,
15                                             unsigned query_type,
16                                             unsigned index)
17 {
18     struct r300_context *r300 = r300_context(pipe);
19     struct r300_screen *r300screen = r300->screen;
20     struct r300_query *q;
21 
22     if (query_type != PIPE_QUERY_OCCLUSION_COUNTER &&
23         query_type != PIPE_QUERY_OCCLUSION_PREDICATE &&
24         query_type != PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE &&
25         query_type != PIPE_QUERY_GPU_FINISHED) {
26         return NULL;
27     }
28 
29     q = CALLOC_STRUCT(r300_query);
30     if (!q)
31         return NULL;
32 
33     q->type = query_type;
34 
35     if (query_type == PIPE_QUERY_GPU_FINISHED) {
36         return (struct pipe_query*)q;
37     }
38 
39     if (r300screen->caps.family == CHIP_RV530)
40         q->num_pipes = r300screen->info.r300_num_z_pipes;
41     else
42         q->num_pipes = r300screen->info.r300_num_gb_pipes;
43 
44     q->buf = r300->rws->buffer_create(r300->rws,
45                                       r300screen->info.gart_page_size,
46                                       r300screen->info.gart_page_size,
47                                       RADEON_DOMAIN_GTT,
48                                       RADEON_FLAG_NO_INTERPROCESS_SHARING);
49     if (!q->buf) {
50         FREE(q);
51         return NULL;
52     }
53     return (struct pipe_query*)q;
54 }
55 
r300_destroy_query(struct pipe_context * pipe,struct pipe_query * query)56 static void r300_destroy_query(struct pipe_context* pipe,
57                                struct pipe_query* query)
58 {
59     struct r300_context *r300 = r300_context(pipe);
60     struct r300_query* q = r300_query(query);
61 
62     radeon_bo_reference(r300->rws, &q->buf, NULL);
63     FREE(query);
64 }
65 
r300_resume_query(struct r300_context * r300,struct r300_query * query)66 void r300_resume_query(struct r300_context *r300,
67                        struct r300_query *query)
68 {
69     r300->query_current = query;
70     r300_mark_atom_dirty(r300, &r300->query_start);
71 }
72 
r300_begin_query(struct pipe_context * pipe,struct pipe_query * query)73 static bool r300_begin_query(struct pipe_context* pipe,
74                              struct pipe_query* query)
75 {
76     struct r300_context* r300 = r300_context(pipe);
77     struct r300_query* q = r300_query(query);
78 
79     if (q->type == PIPE_QUERY_GPU_FINISHED)
80         return true;
81 
82     if (r300->query_current != NULL) {
83         fprintf(stderr, "r300: begin_query: "
84                 "Some other query has already been started.\n");
85         assert(0);
86         return false;
87     }
88 
89     q->num_results = 0;
90     r300_resume_query(r300, q);
91     return true;
92 }
93 
r300_stop_query(struct r300_context * r300)94 void r300_stop_query(struct r300_context *r300)
95 {
96     r300_emit_query_end(r300);
97     r300->query_current = NULL;
98 }
99 
r300_end_query(struct pipe_context * pipe,struct pipe_query * query)100 static bool r300_end_query(struct pipe_context* pipe,
101 	                   struct pipe_query* query)
102 {
103     struct r300_context* r300 = r300_context(pipe);
104     struct r300_query *q = r300_query(query);
105 
106     if (q->type == PIPE_QUERY_GPU_FINISHED) {
107         radeon_bo_reference(r300->rws, &q->buf, NULL);
108         r300_flush(pipe, PIPE_FLUSH_ASYNC,
109                    (struct pipe_fence_handle**)&q->buf);
110         return true;
111     }
112 
113     if (q != r300->query_current) {
114         fprintf(stderr, "r300: end_query: Got invalid query.\n");
115         assert(0);
116         return false;
117     }
118 
119     r300_stop_query(r300);
120 
121     return true;
122 }
123 
r300_get_query_result(struct pipe_context * pipe,struct pipe_query * query,bool wait,union pipe_query_result * vresult)124 static bool r300_get_query_result(struct pipe_context* pipe,
125                                   struct pipe_query* query,
126                                   bool wait,
127                                   union pipe_query_result *vresult)
128 {
129     struct r300_context* r300 = r300_context(pipe);
130     struct r300_query *q = r300_query(query);
131     unsigned i;
132     uint32_t temp, *map;
133 
134     if (q->type == PIPE_QUERY_GPU_FINISHED) {
135         if (wait) {
136             r300->rws->buffer_wait(r300->rws, q->buf, OS_TIMEOUT_INFINITE,
137                                    RADEON_USAGE_READWRITE);
138             vresult->b = true;
139         } else {
140             vresult->b = r300->rws->buffer_wait(r300->rws, q->buf, 0, RADEON_USAGE_READWRITE);
141         }
142         return vresult->b;
143     }
144 
145     map = r300->rws->buffer_map(r300->rws, q->buf, &r300->cs,
146                                 PIPE_MAP_READ |
147                                 (!wait ? PIPE_MAP_DONTBLOCK : 0));
148     if (!map)
149         return false;
150 
151     /* Sum up the results. */
152     temp = 0;
153     for (i = 0; i < q->num_results; i++) {
154         /* Convert little endian values written by GPU to CPU byte order */
155         temp += util_le32_to_cpu(*map);
156         map++;
157     }
158 
159     if (q->type == PIPE_QUERY_OCCLUSION_PREDICATE ||
160         q->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE) {
161         vresult->b = temp != 0;
162     } else {
163         vresult->u64 = temp;
164     }
165     return true;
166 }
167 
r300_render_condition(struct pipe_context * pipe,struct pipe_query * query,bool condition,enum pipe_render_cond_flag mode)168 static void r300_render_condition(struct pipe_context *pipe,
169                                   struct pipe_query *query,
170                                   bool condition,
171                                   enum pipe_render_cond_flag mode)
172 {
173     struct r300_context *r300 = r300_context(pipe);
174     union pipe_query_result result;
175     bool wait;
176 
177     r300->skip_rendering = false;
178 
179     if (query) {
180         wait = mode == PIPE_RENDER_COND_WAIT ||
181                mode == PIPE_RENDER_COND_BY_REGION_WAIT;
182 
183         if (r300_get_query_result(pipe, query, wait, &result)) {
184             if (r300_query(query)->type == PIPE_QUERY_OCCLUSION_PREDICATE ||
185                 r300_query(query)->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE) {
186                 r300->skip_rendering = condition == result.b;
187             } else {
188                 r300->skip_rendering = condition == !!result.u64;
189             }
190         }
191     }
192 }
193 
194 static void
r300_set_active_query_state(struct pipe_context * pipe,bool enable)195 r300_set_active_query_state(struct pipe_context *pipe, bool enable)
196 {
197 }
198 
r300_init_query_functions(struct r300_context * r300)199 void r300_init_query_functions(struct r300_context* r300)
200 {
201     r300->context.create_query = r300_create_query;
202     r300->context.destroy_query = r300_destroy_query;
203     r300->context.begin_query = r300_begin_query;
204     r300->context.end_query = r300_end_query;
205     r300->context.get_query_result = r300_get_query_result;
206     r300->context.set_active_query_state = r300_set_active_query_state;
207     r300->context.render_condition = r300_render_condition;
208 }
209