2 * Copyright 2011 Nouveau Project
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
22 * Authors: Christoph Bumiller
25 #define NVC0_PUSH_EXPLICIT_SPACE_CHECKING
27 #include "nvc0/nvc0_context.h"
28 #include "nvc0/nvc0_query.h"
29 #include "nvc0/nvc0_query_sw.h"
30 #include "nvc0/nvc0_query_hw.h"
31 #include "nvc0/nvc0_query_hw_metric.h"
32 #include "nvc0/nvc0_query_hw_sm.h"
34 static struct pipe_query
*
35 nvc0_create_query(struct pipe_context
*pipe
, unsigned type
, unsigned index
)
37 struct nvc0_context
*nvc0
= nvc0_context(pipe
);
40 q
= nvc0_sw_create_query(nvc0
, type
, index
);
42 q
= nvc0_hw_create_query(nvc0
, type
, index
);
44 return (struct pipe_query
*)q
;
48 nvc0_destroy_query(struct pipe_context
*pipe
, struct pipe_query
*pq
)
50 struct nvc0_query
*q
= nvc0_query(pq
);
51 q
->funcs
->destroy_query(nvc0_context(pipe
), q
);
55 nvc0_begin_query(struct pipe_context
*pipe
, struct pipe_query
*pq
)
57 struct nvc0_query
*q
= nvc0_query(pq
);
58 return q
->funcs
->begin_query(nvc0_context(pipe
), q
);
62 nvc0_end_query(struct pipe_context
*pipe
, struct pipe_query
*pq
)
64 struct nvc0_query
*q
= nvc0_query(pq
);
65 q
->funcs
->end_query(nvc0_context(pipe
), q
);
70 nvc0_get_query_result(struct pipe_context
*pipe
, struct pipe_query
*pq
,
71 bool wait
, union pipe_query_result
*result
)
73 struct nvc0_query
*q
= nvc0_query(pq
);
74 return q
->funcs
->get_query_result(nvc0_context(pipe
), q
, wait
, result
);
78 nvc0_get_query_result_resource(struct pipe_context
*pipe
,
79 struct pipe_query
*pq
,
81 enum pipe_query_value_type result_type
,
83 struct pipe_resource
*resource
,
86 struct nvc0_query
*q
= nvc0_query(pq
);
87 if (!q
->funcs
->get_query_result_resource
) {
88 assert(!"Unexpected lack of get_query_result_resource");
91 q
->funcs
->get_query_result_resource(nvc0_context(pipe
), q
, wait
, result_type
,
92 index
, resource
, offset
);
96 nvc0_render_condition(struct pipe_context
*pipe
,
97 struct pipe_query
*pq
,
98 bool condition
, enum pipe_render_cond_flag mode
)
100 struct nvc0_context
*nvc0
= nvc0_context(pipe
);
101 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
102 struct nvc0_query
*q
= nvc0_query(pq
);
103 struct nvc0_hw_query
*hq
= nvc0_hw_query(q
);
106 mode
!= PIPE_RENDER_COND_NO_WAIT
&&
107 mode
!= PIPE_RENDER_COND_BY_REGION_NO_WAIT
;
110 cond
= NVC0_3D_COND_MODE_ALWAYS
;
113 /* NOTE: comparison of 2 queries only works if both have completed */
115 case PIPE_QUERY_SO_OVERFLOW_PREDICATE
:
116 case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE
:
117 cond
= condition
? NVC0_3D_COND_MODE_EQUAL
:
118 NVC0_3D_COND_MODE_NOT_EQUAL
;
121 case PIPE_QUERY_OCCLUSION_COUNTER
:
122 case PIPE_QUERY_OCCLUSION_PREDICATE
:
123 case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE
:
124 if (hq
->state
== NVC0_HW_QUERY_STATE_READY
)
126 if (likely(!condition
)) {
127 cond
= wait
? NVC0_3D_COND_MODE_NOT_EQUAL
: NVC0_3D_COND_MODE_ALWAYS
;
129 cond
= wait
? NVC0_3D_COND_MODE_EQUAL
: NVC0_3D_COND_MODE_ALWAYS
;
133 assert(!"render condition query not a predicate");
134 cond
= NVC0_3D_COND_MODE_ALWAYS
;
139 nvc0
->cond_query
= pq
;
140 nvc0
->cond_cond
= condition
;
141 nvc0
->cond_condmode
= cond
;
142 nvc0
->cond_mode
= mode
;
146 IMMED_NVC0(push
, NVC0_3D(COND_MODE
), cond
);
147 if (nvc0
->screen
->compute
)
148 IMMED_NVC0(push
, NVC0_CP(COND_MODE
), cond
);
152 if (wait
&& hq
->state
!= NVC0_HW_QUERY_STATE_READY
)
153 nvc0_hw_query_fifo_wait(nvc0
, q
);
155 PUSH_SPACE(push
, 10);
156 PUSH_REFN (push
, hq
->bo
, NOUVEAU_BO_GART
| NOUVEAU_BO_RD
);
157 BEGIN_NVC0(push
, NVC0_3D(COND_ADDRESS_HIGH
), 3);
158 PUSH_DATAh(push
, hq
->bo
->offset
+ hq
->offset
);
159 PUSH_DATA (push
, hq
->bo
->offset
+ hq
->offset
);
160 PUSH_DATA (push
, cond
);
161 BEGIN_NVC0(push
, NVC0_2D(COND_ADDRESS_HIGH
), 2);
162 PUSH_DATAh(push
, hq
->bo
->offset
+ hq
->offset
);
163 PUSH_DATA (push
, hq
->bo
->offset
+ hq
->offset
);
164 if (nvc0
->screen
->compute
) {
165 BEGIN_NVC0(push
, NVC0_CP(COND_ADDRESS_HIGH
), 3);
166 PUSH_DATAh(push
, hq
->bo
->offset
+ hq
->offset
);
167 PUSH_DATA (push
, hq
->bo
->offset
+ hq
->offset
);
168 PUSH_DATA (push
, cond
);
173 nvc0_screen_get_driver_query_info(struct pipe_screen
*pscreen
,
175 struct pipe_driver_query_info
*info
)
177 struct nvc0_screen
*screen
= nvc0_screen(pscreen
);
178 int num_sw_queries
= 0, num_hw_queries
= 0;
180 num_sw_queries
= nvc0_sw_get_driver_query_info(screen
, 0, NULL
);
181 num_hw_queries
= nvc0_hw_get_driver_query_info(screen
, 0, NULL
);
184 return num_sw_queries
+ num_hw_queries
;
186 /* Init default values. */
187 info
->name
= "this_is_not_the_query_you_are_looking_for";
188 info
->query_type
= 0xdeadd01d;
189 info
->max_value
.u64
= 0;
190 info
->type
= PIPE_DRIVER_QUERY_TYPE_UINT64
;
194 #ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
195 if (id
< num_sw_queries
)
196 return nvc0_sw_get_driver_query_info(screen
, id
, info
);
199 return nvc0_hw_get_driver_query_info(screen
, id
- num_sw_queries
, info
);
203 nvc0_screen_get_driver_query_group_info(struct pipe_screen
*pscreen
,
205 struct pipe_driver_query_group_info
*info
)
207 struct nvc0_screen
*screen
= nvc0_screen(pscreen
);
210 #ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
214 if (screen
->base
.drm
->version
>= 0x01000101) {
215 if (screen
->compute
) {
216 if (screen
->base
.class_3d
<= GM200_3D_CLASS
) {
225 if (id
== NVC0_HW_SM_QUERY_GROUP
) {
226 if (screen
->compute
) {
227 info
->name
= "MP counters";
229 /* Expose the maximum number of hardware counters available, although
230 * some queries use more than one counter. Expect failures in that
231 * case but as performance counters are for developers, this should
232 * not have a real impact. */
233 info
->max_active_queries
= 8;
234 info
->num_queries
= nvc0_hw_sm_get_num_queries(screen
);
238 if (id
== NVC0_HW_METRIC_QUERY_GROUP
) {
239 if (screen
->compute
) {
240 if (screen
->base
.class_3d
<= GM200_3D_CLASS
) {
241 info
->name
= "Performance metrics";
242 info
->max_active_queries
= 4; /* A metric uses at least 2 queries */
243 info
->num_queries
= nvc0_hw_metric_get_num_queries(screen
);
248 #ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
249 else if (id
== NVC0_SW_QUERY_DRV_STAT_GROUP
) {
250 info
->name
= "Driver statistics";
251 info
->max_active_queries
= NVC0_SW_QUERY_DRV_STAT_COUNT
;
252 info
->num_queries
= NVC0_SW_QUERY_DRV_STAT_COUNT
;
257 /* user asked for info about non-existing query group */
258 info
->name
= "this_is_not_the_query_group_you_are_looking_for";
259 info
->max_active_queries
= 0;
260 info
->num_queries
= 0;
265 nvc0_set_active_query_state(struct pipe_context
*pipe
, bool enable
)
270 nvc0_init_query_functions(struct nvc0_context
*nvc0
)
272 struct pipe_context
*pipe
= &nvc0
->base
.pipe
;
274 pipe
->create_query
= nvc0_create_query
;
275 pipe
->destroy_query
= nvc0_destroy_query
;
276 pipe
->begin_query
= nvc0_begin_query
;
277 pipe
->end_query
= nvc0_end_query
;
278 pipe
->get_query_result
= nvc0_get_query_result
;
279 pipe
->get_query_result_resource
= nvc0_get_query_result_resource
;
280 pipe
->set_active_query_state
= nvc0_set_active_query_state
;
281 pipe
->render_condition
= nvc0_render_condition
;
282 nvc0
->cond_condmode
= NVC0_3D_COND_MODE_ALWAYS
;