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
);
69 nvc0_get_query_result(struct pipe_context
*pipe
, struct pipe_query
*pq
,
70 boolean wait
, union pipe_query_result
*result
)
72 struct nvc0_query
*q
= nvc0_query(pq
);
73 return q
->funcs
->get_query_result(nvc0_context(pipe
), q
, wait
, result
);
77 nvc0_get_query_result_resource(struct pipe_context
*pipe
,
78 struct pipe_query
*pq
,
80 enum pipe_query_value_type result_type
,
82 struct pipe_resource
*resource
,
85 struct nvc0_query
*q
= nvc0_query(pq
);
86 if (!q
->funcs
->get_query_result_resource
) {
87 assert(!"Unexpected lack of get_query_result_resource");
90 q
->funcs
->get_query_result_resource(nvc0_context(pipe
), q
, wait
, result_type
,
91 index
, resource
, offset
);
95 nvc0_render_condition(struct pipe_context
*pipe
,
96 struct pipe_query
*pq
,
97 boolean condition
, uint mode
)
99 struct nvc0_context
*nvc0
= nvc0_context(pipe
);
100 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
101 struct nvc0_query
*q
= nvc0_query(pq
);
102 struct nvc0_hw_query
*hq
= nvc0_hw_query(q
);
105 mode
!= PIPE_RENDER_COND_NO_WAIT
&&
106 mode
!= PIPE_RENDER_COND_BY_REGION_NO_WAIT
;
109 cond
= NVC0_3D_COND_MODE_ALWAYS
;
112 /* NOTE: comparison of 2 queries only works if both have completed */
114 case PIPE_QUERY_SO_OVERFLOW_PREDICATE
:
115 cond
= condition
? NVC0_3D_COND_MODE_EQUAL
:
116 NVC0_3D_COND_MODE_NOT_EQUAL
;
119 case PIPE_QUERY_OCCLUSION_COUNTER
:
120 case PIPE_QUERY_OCCLUSION_PREDICATE
:
121 if (likely(!condition
)) {
122 if (unlikely(hq
->nesting
))
123 cond
= wait
? NVC0_3D_COND_MODE_NOT_EQUAL
:
124 NVC0_3D_COND_MODE_ALWAYS
;
126 cond
= NVC0_3D_COND_MODE_RES_NON_ZERO
;
128 cond
= wait
? NVC0_3D_COND_MODE_EQUAL
: NVC0_3D_COND_MODE_ALWAYS
;
132 assert(!"render condition query not a predicate");
133 cond
= NVC0_3D_COND_MODE_ALWAYS
;
138 nvc0
->cond_query
= pq
;
139 nvc0
->cond_cond
= condition
;
140 nvc0
->cond_condmode
= cond
;
141 nvc0
->cond_mode
= mode
;
145 IMMED_NVC0(push
, NVC0_3D(COND_MODE
), cond
);
150 nvc0_hw_query_fifo_wait(nvc0
, q
);
153 PUSH_REFN (push
, hq
->bo
, NOUVEAU_BO_GART
| NOUVEAU_BO_RD
);
154 BEGIN_NVC0(push
, NVC0_3D(COND_ADDRESS_HIGH
), 3);
155 PUSH_DATAh(push
, hq
->bo
->offset
+ hq
->offset
);
156 PUSH_DATA (push
, hq
->bo
->offset
+ hq
->offset
);
157 PUSH_DATA (push
, cond
);
158 BEGIN_NVC0(push
, NVC0_2D(COND_ADDRESS_HIGH
), 2);
159 PUSH_DATAh(push
, hq
->bo
->offset
+ hq
->offset
);
160 PUSH_DATA (push
, hq
->bo
->offset
+ hq
->offset
);
164 nvc0_screen_get_driver_query_info(struct pipe_screen
*pscreen
,
166 struct pipe_driver_query_info
*info
)
168 struct nvc0_screen
*screen
= nvc0_screen(pscreen
);
169 int num_sw_queries
= 0, num_hw_queries
= 0;
171 num_sw_queries
= nvc0_sw_get_driver_query_info(screen
, 0, NULL
);
172 num_hw_queries
= nvc0_hw_get_driver_query_info(screen
, 0, NULL
);
175 return num_sw_queries
+ num_hw_queries
;
177 /* Init default values. */
178 info
->name
= "this_is_not_the_query_you_are_looking_for";
179 info
->query_type
= 0xdeadd01d;
180 info
->max_value
.u64
= 0;
181 info
->type
= PIPE_DRIVER_QUERY_TYPE_UINT64
;
185 #ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
186 if (id
< num_sw_queries
)
187 return nvc0_sw_get_driver_query_info(screen
, id
, info
);
190 return nvc0_hw_get_driver_query_info(screen
, id
- num_sw_queries
, info
);
194 nvc0_screen_get_driver_query_group_info(struct pipe_screen
*pscreen
,
196 struct pipe_driver_query_group_info
*info
)
198 struct nvc0_screen
*screen
= nvc0_screen(pscreen
);
201 #ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
205 if (screen
->base
.drm
->version
>= 0x01000101) {
206 if (screen
->compute
) {
207 if (screen
->base
.class_3d
<= NVE4_3D_CLASS
) {
216 if (id
== NVC0_HW_SM_QUERY_GROUP
) {
217 if (screen
->compute
) {
218 info
->name
= "MP counters";
220 /* Because we can't expose the number of hardware counters needed for
221 * each different query, we don't want to allow more than one active
222 * query simultaneously to avoid failure when the maximum number of
223 * counters is reached. Note that these groups of GPU counters are
224 * currently only used by AMD_performance_monitor.
226 info
->max_active_queries
= 1;
227 info
->num_queries
= nvc0_hw_sm_get_num_queries(screen
);
231 if (id
== NVC0_HW_METRIC_QUERY_GROUP
) {
232 if (screen
->compute
) {
233 if (screen
->base
.class_3d
<= NVE4_3D_CLASS
) {
234 info
->name
= "Performance metrics";
235 info
->max_active_queries
= 1;
236 info
->num_queries
= nvc0_hw_metric_get_num_queries(screen
);
241 #ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
242 else if (id
== NVC0_SW_QUERY_DRV_STAT_GROUP
) {
243 info
->name
= "Driver statistics";
244 info
->max_active_queries
= NVC0_SW_QUERY_DRV_STAT_COUNT
;
245 info
->num_queries
= NVC0_SW_QUERY_DRV_STAT_COUNT
;
250 /* user asked for info about non-existing query group */
251 info
->name
= "this_is_not_the_query_group_you_are_looking_for";
252 info
->max_active_queries
= 0;
253 info
->num_queries
= 0;
258 nvc0_init_query_functions(struct nvc0_context
*nvc0
)
260 struct pipe_context
*pipe
= &nvc0
->base
.pipe
;
262 pipe
->create_query
= nvc0_create_query
;
263 pipe
->destroy_query
= nvc0_destroy_query
;
264 pipe
->begin_query
= nvc0_begin_query
;
265 pipe
->end_query
= nvc0_end_query
;
266 pipe
->get_query_result
= nvc0_get_query_result
;
267 pipe
->get_query_result_resource
= nvc0_get_query_result_resource
;
268 pipe
->render_condition
= nvc0_render_condition
;
269 nvc0
->cond_condmode
= NVC0_3D_COND_MODE_ALWAYS
;