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 boolean 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 boolean condition
, uint 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 cond
= condition
? NVC0_3D_COND_MODE_EQUAL
:
117 NVC0_3D_COND_MODE_NOT_EQUAL
;
120 case PIPE_QUERY_OCCLUSION_COUNTER
:
121 case PIPE_QUERY_OCCLUSION_PREDICATE
:
122 if (likely(!condition
)) {
123 if (unlikely(hq
->nesting
))
124 cond
= wait
? NVC0_3D_COND_MODE_NOT_EQUAL
:
125 NVC0_3D_COND_MODE_ALWAYS
;
127 cond
= NVC0_3D_COND_MODE_RES_NON_ZERO
;
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
);
151 nvc0_hw_query_fifo_wait(nvc0
, q
);
154 PUSH_REFN (push
, hq
->bo
, NOUVEAU_BO_GART
| NOUVEAU_BO_RD
);
155 BEGIN_NVC0(push
, NVC0_3D(COND_ADDRESS_HIGH
), 3);
156 PUSH_DATAh(push
, hq
->bo
->offset
+ hq
->offset
);
157 PUSH_DATA (push
, hq
->bo
->offset
+ hq
->offset
);
158 PUSH_DATA (push
, cond
);
159 BEGIN_NVC0(push
, NVC0_2D(COND_ADDRESS_HIGH
), 2);
160 PUSH_DATAh(push
, hq
->bo
->offset
+ hq
->offset
);
161 PUSH_DATA (push
, hq
->bo
->offset
+ hq
->offset
);
165 nvc0_screen_get_driver_query_info(struct pipe_screen
*pscreen
,
167 struct pipe_driver_query_info
*info
)
169 struct nvc0_screen
*screen
= nvc0_screen(pscreen
);
170 int num_sw_queries
= 0, num_hw_queries
= 0;
172 num_sw_queries
= nvc0_sw_get_driver_query_info(screen
, 0, NULL
);
173 num_hw_queries
= nvc0_hw_get_driver_query_info(screen
, 0, NULL
);
176 return num_sw_queries
+ num_hw_queries
;
178 /* Init default values. */
179 info
->name
= "this_is_not_the_query_you_are_looking_for";
180 info
->query_type
= 0xdeadd01d;
181 info
->max_value
.u64
= 0;
182 info
->type
= PIPE_DRIVER_QUERY_TYPE_UINT64
;
186 #ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
187 if (id
< num_sw_queries
)
188 return nvc0_sw_get_driver_query_info(screen
, id
, info
);
191 return nvc0_hw_get_driver_query_info(screen
, id
- num_sw_queries
, info
);
195 nvc0_screen_get_driver_query_group_info(struct pipe_screen
*pscreen
,
197 struct pipe_driver_query_group_info
*info
)
199 struct nvc0_screen
*screen
= nvc0_screen(pscreen
);
202 #ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
206 if (screen
->base
.drm
->version
>= 0x01000101) {
207 if (screen
->compute
) {
208 if (screen
->base
.class_3d
<= NVF0_3D_CLASS
) {
217 if (id
== NVC0_HW_SM_QUERY_GROUP
) {
218 if (screen
->compute
) {
219 info
->name
= "MP counters";
221 /* Because we can't expose the number of hardware counters needed for
222 * each different query, we don't want to allow more than one active
223 * query simultaneously to avoid failure when the maximum number of
224 * counters is reached. Note that these groups of GPU counters are
225 * currently only used by AMD_performance_monitor.
227 info
->max_active_queries
= 1;
228 info
->num_queries
= nvc0_hw_sm_get_num_queries(screen
);
232 if (id
== NVC0_HW_METRIC_QUERY_GROUP
) {
233 if (screen
->compute
) {
234 if (screen
->base
.class_3d
<= NVF0_3D_CLASS
) {
235 info
->name
= "Performance metrics";
236 info
->max_active_queries
= 1;
237 info
->num_queries
= nvc0_hw_metric_get_num_queries(screen
);
242 #ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
243 else if (id
== NVC0_SW_QUERY_DRV_STAT_GROUP
) {
244 info
->name
= "Driver statistics";
245 info
->max_active_queries
= NVC0_SW_QUERY_DRV_STAT_COUNT
;
246 info
->num_queries
= NVC0_SW_QUERY_DRV_STAT_COUNT
;
251 /* user asked for info about non-existing query group */
252 info
->name
= "this_is_not_the_query_group_you_are_looking_for";
253 info
->max_active_queries
= 0;
254 info
->num_queries
= 0;
259 nvc0_set_active_query_state(struct pipe_context
*pipe
, boolean enable
)
264 nvc0_init_query_functions(struct nvc0_context
*nvc0
)
266 struct pipe_context
*pipe
= &nvc0
->base
.pipe
;
268 pipe
->create_query
= nvc0_create_query
;
269 pipe
->destroy_query
= nvc0_destroy_query
;
270 pipe
->begin_query
= nvc0_begin_query
;
271 pipe
->end_query
= nvc0_end_query
;
272 pipe
->get_query_result
= nvc0_get_query_result
;
273 pipe
->get_query_result_resource
= nvc0_get_query_result_resource
;
274 pipe
->set_active_query_state
= nvc0_set_active_query_state
;
275 pipe
->render_condition
= nvc0_render_condition
;
276 nvc0
->cond_condmode
= NVC0_3D_COND_MODE_ALWAYS
;