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 NV50_PUSH_EXPLICIT_SPACE_CHECKING
27 #include "nv50/nv50_context.h"
28 #include "nv50/nv50_query.h"
29 #include "nv50/nv50_query_hw.h"
30 #include "nv50/nv50_query_hw_metric.h"
31 #include "nv50/nv50_query_hw_sm.h"
33 static struct pipe_query
*
34 nv50_create_query(struct pipe_context
*pipe
, unsigned type
, unsigned index
)
36 struct nv50_context
*nv50
= nv50_context(pipe
);
39 q
= nv50_hw_create_query(nv50
, type
, index
);
40 return (struct pipe_query
*)q
;
44 nv50_destroy_query(struct pipe_context
*pipe
, struct pipe_query
*pq
)
46 struct nv50_query
*q
= nv50_query(pq
);
47 q
->funcs
->destroy_query(nv50_context(pipe
), q
);
51 nv50_begin_query(struct pipe_context
*pipe
, struct pipe_query
*pq
)
53 struct nv50_query
*q
= nv50_query(pq
);
54 return q
->funcs
->begin_query(nv50_context(pipe
), q
);
58 nv50_end_query(struct pipe_context
*pipe
, struct pipe_query
*pq
)
60 struct nv50_query
*q
= nv50_query(pq
);
61 q
->funcs
->end_query(nv50_context(pipe
), q
);
66 nv50_get_query_result(struct pipe_context
*pipe
, struct pipe_query
*pq
,
67 boolean wait
, union pipe_query_result
*result
)
69 struct nv50_query
*q
= nv50_query(pq
);
70 return q
->funcs
->get_query_result(nv50_context(pipe
), q
, wait
, result
);
74 nv50_render_condition(struct pipe_context
*pipe
,
75 struct pipe_query
*pq
,
76 boolean condition
, enum pipe_render_cond_flag mode
)
78 struct nv50_context
*nv50
= nv50_context(pipe
);
79 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
80 struct nv50_query
*q
= nv50_query(pq
);
81 struct nv50_hw_query
*hq
= nv50_hw_query(q
);
84 mode
!= PIPE_RENDER_COND_NO_WAIT
&&
85 mode
!= PIPE_RENDER_COND_BY_REGION_NO_WAIT
;
88 cond
= NV50_3D_COND_MODE_ALWAYS
;
91 /* NOTE: comparison of 2 queries only works if both have completed */
93 case PIPE_QUERY_SO_OVERFLOW_PREDICATE
:
94 cond
= condition
? NV50_3D_COND_MODE_EQUAL
:
95 NV50_3D_COND_MODE_NOT_EQUAL
;
98 case PIPE_QUERY_OCCLUSION_COUNTER
:
99 case PIPE_QUERY_OCCLUSION_PREDICATE
:
100 case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE
:
101 if (hq
->state
== NV50_HW_QUERY_STATE_READY
)
103 if (likely(!condition
)) {
104 cond
= wait
? NV50_3D_COND_MODE_NOT_EQUAL
: NV50_3D_COND_MODE_ALWAYS
;
106 cond
= wait
? NV50_3D_COND_MODE_EQUAL
: NV50_3D_COND_MODE_ALWAYS
;
110 assert(!"render condition query not a predicate");
111 cond
= NV50_3D_COND_MODE_ALWAYS
;
116 nv50
->cond_query
= pq
;
117 nv50
->cond_cond
= condition
;
118 nv50
->cond_condmode
= cond
;
119 nv50
->cond_mode
= mode
;
123 BEGIN_NV04(push
, NV50_3D(COND_MODE
), 1);
124 PUSH_DATA (push
, cond
);
130 if (wait
&& hq
->state
!= NV50_HW_QUERY_STATE_READY
) {
131 BEGIN_NV04(push
, SUBC_3D(NV50_GRAPH_SERIALIZE
), 1);
135 PUSH_REFN (push
, hq
->bo
, NOUVEAU_BO_GART
| NOUVEAU_BO_RD
);
136 BEGIN_NV04(push
, NV50_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
);
141 BEGIN_NV04(push
, NV50_2D(COND_ADDRESS_HIGH
), 2);
142 PUSH_DATAh(push
, hq
->bo
->offset
+ hq
->offset
);
143 PUSH_DATA (push
, hq
->bo
->offset
+ hq
->offset
);
147 nv50_set_active_query_state(struct pipe_context
*pipe
, boolean enable
)
152 nv50_init_query_functions(struct nv50_context
*nv50
)
154 struct pipe_context
*pipe
= &nv50
->base
.pipe
;
156 pipe
->create_query
= nv50_create_query
;
157 pipe
->destroy_query
= nv50_destroy_query
;
158 pipe
->begin_query
= nv50_begin_query
;
159 pipe
->end_query
= nv50_end_query
;
160 pipe
->get_query_result
= nv50_get_query_result
;
161 pipe
->set_active_query_state
= nv50_set_active_query_state
;
162 pipe
->render_condition
= nv50_render_condition
;
163 nv50
->cond_condmode
= NV50_3D_COND_MODE_ALWAYS
;
167 nv50_screen_get_driver_query_info(struct pipe_screen
*pscreen
,
169 struct pipe_driver_query_info
*info
)
171 struct nv50_screen
*screen
= nv50_screen(pscreen
);
172 int num_hw_queries
= 0;
174 num_hw_queries
= nv50_hw_get_driver_query_info(screen
, 0, NULL
);
177 return num_hw_queries
;
179 /* Init default values. */
180 info
->name
= "this_is_not_the_query_you_are_looking_for";
181 info
->query_type
= 0xdeadd01d;
182 info
->max_value
.u64
= 0;
183 info
->type
= PIPE_DRIVER_QUERY_TYPE_UINT64
;
187 return nv50_hw_get_driver_query_info(screen
, id
, info
);
191 nv50_screen_get_driver_query_group_info(struct pipe_screen
*pscreen
,
193 struct pipe_driver_query_group_info
*info
)
195 struct nv50_screen
*screen
= nv50_screen(pscreen
);
199 if (screen
->base
.class_3d
>= NV84_3D_CLASS
)
205 if (id
== NV50_HW_SM_QUERY_GROUP
) {
206 if (screen
->compute
) {
207 if (screen
->base
.class_3d
>= NV84_3D_CLASS
) {
208 info
->name
= "MP counters";
210 /* Expose the maximum number of hardware counters available,
211 * although some queries use more than one counter. Expect failures
212 * in that case but as performance counters are for developers,
213 * this should not have a real impact. */
214 info
->max_active_queries
= 4;
215 info
->num_queries
= NV50_HW_SM_QUERY_COUNT
;
220 if (id
== NV50_HW_METRIC_QUERY_GROUP
) {
221 if (screen
->compute
) {
222 if (screen
->base
.class_3d
>= NV84_3D_CLASS
) {
223 info
->name
= "Performance metrics";
224 info
->max_active_queries
= 2; /* A metric uses at least 2 queries */
225 info
->num_queries
= NV50_HW_METRIC_QUERY_COUNT
;
231 /* user asked for info about non-existing query group */
232 info
->name
= "this_is_not_the_query_group_you_are_looking_for";
233 info
->max_active_queries
= 0;
234 info
->num_queries
= 0;