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_render_condition(struct pipe_context
*pipe
,
78 struct pipe_query
*pq
,
79 boolean condition
, uint mode
)
81 struct nvc0_context
*nvc0
= nvc0_context(pipe
);
82 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
83 struct nvc0_query
*q
= nvc0_query(pq
);
84 struct nvc0_hw_query
*hq
= nvc0_hw_query(q
);
87 mode
!= PIPE_RENDER_COND_NO_WAIT
&&
88 mode
!= PIPE_RENDER_COND_BY_REGION_NO_WAIT
;
91 cond
= NVC0_3D_COND_MODE_ALWAYS
;
94 /* NOTE: comparison of 2 queries only works if both have completed */
96 case PIPE_QUERY_SO_OVERFLOW_PREDICATE
:
97 cond
= condition
? NVC0_3D_COND_MODE_EQUAL
:
98 NVC0_3D_COND_MODE_NOT_EQUAL
;
101 case PIPE_QUERY_OCCLUSION_COUNTER
:
102 case PIPE_QUERY_OCCLUSION_PREDICATE
:
103 if (likely(!condition
)) {
104 if (unlikely(hq
->nesting
))
105 cond
= wait
? NVC0_3D_COND_MODE_NOT_EQUAL
:
106 NVC0_3D_COND_MODE_ALWAYS
;
108 cond
= NVC0_3D_COND_MODE_RES_NON_ZERO
;
110 cond
= wait
? NVC0_3D_COND_MODE_EQUAL
: NVC0_3D_COND_MODE_ALWAYS
;
114 assert(!"render condition query not a predicate");
115 cond
= NVC0_3D_COND_MODE_ALWAYS
;
120 nvc0
->cond_query
= pq
;
121 nvc0
->cond_cond
= condition
;
122 nvc0
->cond_condmode
= cond
;
123 nvc0
->cond_mode
= mode
;
127 IMMED_NVC0(push
, NVC0_3D(COND_MODE
), cond
);
132 nvc0_hw_query_fifo_wait(push
, q
);
135 PUSH_REFN (push
, hq
->bo
, NOUVEAU_BO_GART
| NOUVEAU_BO_RD
);
136 BEGIN_NVC0(push
, NVC0_3D(COND_ADDRESS_HIGH
), 3);
137 PUSH_DATAh(push
, hq
->bo
->offset
+ hq
->offset
);
138 PUSH_DATA (push
, hq
->bo
->offset
+ hq
->offset
);
139 PUSH_DATA (push
, cond
);
140 BEGIN_NVC0(push
, NVC0_2D(COND_ADDRESS_HIGH
), 2);
141 PUSH_DATAh(push
, hq
->bo
->offset
+ hq
->offset
);
142 PUSH_DATA (push
, hq
->bo
->offset
+ hq
->offset
);
146 nvc0_screen_get_driver_query_info(struct pipe_screen
*pscreen
,
148 struct pipe_driver_query_info
*info
)
150 struct nvc0_screen
*screen
= nvc0_screen(pscreen
);
151 int num_sw_queries
= 0, num_hw_queries
= 0;
153 num_sw_queries
= nvc0_sw_get_driver_query_info(screen
, 0, NULL
);
154 num_hw_queries
= nvc0_hw_get_driver_query_info(screen
, 0, NULL
);
157 return num_sw_queries
+ num_hw_queries
;
159 /* Init default values. */
160 info
->name
= "this_is_not_the_query_you_are_looking_for";
161 info
->query_type
= 0xdeadd01d;
162 info
->max_value
.u64
= 0;
163 info
->type
= PIPE_DRIVER_QUERY_TYPE_UINT64
;
166 #ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
167 if (id
< num_sw_queries
)
168 return nvc0_sw_get_driver_query_info(screen
, id
, info
);
171 return nvc0_hw_get_driver_query_info(screen
, id
- num_sw_queries
, info
);
175 nvc0_screen_get_driver_query_group_info(struct pipe_screen
*pscreen
,
177 struct pipe_driver_query_group_info
*info
)
179 struct nvc0_screen
*screen
= nvc0_screen(pscreen
);
182 #ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
186 if (screen
->base
.device
->drm_version
>= 0x01000101) {
187 if (screen
->compute
) {
188 if (screen
->base
.class_3d
== NVE4_3D_CLASS
) {
191 if (screen
->base
.class_3d
< NVE4_3D_CLASS
) {
200 if (id
== NVC0_HW_SM_QUERY_GROUP
) {
201 if (screen
->compute
) {
202 info
->name
= "MP counters";
203 info
->type
= PIPE_DRIVER_QUERY_GROUP_TYPE_GPU
;
205 /* Because we can't expose the number of hardware counters needed for
206 * each different query, we don't want to allow more than one active
207 * query simultaneously to avoid failure when the maximum number of
208 * counters is reached. Note that these groups of GPU counters are
209 * currently only used by AMD_performance_monitor.
211 info
->max_active_queries
= 1;
213 if (screen
->base
.class_3d
== NVE4_3D_CLASS
) {
214 info
->num_queries
= NVE4_HW_SM_QUERY_COUNT
;
217 if (screen
->base
.class_3d
< NVE4_3D_CLASS
) {
218 info
->num_queries
= NVC0_HW_SM_QUERY_COUNT
;
223 if (id
== NVC0_HW_METRIC_QUERY_GROUP
) {
224 if (screen
->compute
) {
225 if (screen
->base
.class_3d
< NVE4_3D_CLASS
) {
226 info
->name
= "Performance metrics";
227 info
->type
= PIPE_DRIVER_QUERY_GROUP_TYPE_GPU
;
228 info
->max_active_queries
= 1;
229 info
->num_queries
= NVC0_HW_METRIC_QUERY_COUNT
;
234 #ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
235 else if (id
== NVC0_SW_QUERY_DRV_STAT_GROUP
) {
236 info
->name
= "Driver statistics";
237 info
->type
= PIPE_DRIVER_QUERY_GROUP_TYPE_CPU
;
238 info
->max_active_queries
= NVC0_SW_QUERY_DRV_STAT_COUNT
;
239 info
->num_queries
= NVC0_SW_QUERY_DRV_STAT_COUNT
;
244 /* user asked for info about non-existing query group */
245 info
->name
= "this_is_not_the_query_group_you_are_looking_for";
246 info
->max_active_queries
= 0;
247 info
->num_queries
= 0;
253 nvc0_init_query_functions(struct nvc0_context
*nvc0
)
255 struct pipe_context
*pipe
= &nvc0
->base
.pipe
;
257 pipe
->create_query
= nvc0_create_query
;
258 pipe
->destroy_query
= nvc0_destroy_query
;
259 pipe
->begin_query
= nvc0_begin_query
;
260 pipe
->end_query
= nvc0_end_query
;
261 pipe
->get_query_result
= nvc0_get_query_result
;
262 pipe
->render_condition
= nvc0_render_condition
;