2 * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
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 (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * Rob Clark <robclark@freedesktop.org>
27 #include "pipe/p_state.h"
28 #include "util/u_string.h"
29 #include "util/u_memory.h"
30 #include "util/u_inlines.h"
31 #include "util/os_time.h"
33 #include "freedreno_query_sw.h"
34 #include "freedreno_context.h"
35 #include "freedreno_util.h"
40 * In the core, we have some support for basic sw counters
44 fd_sw_destroy_query(struct fd_context
*ctx
, struct fd_query
*q
)
46 struct fd_sw_query
*sq
= fd_sw_query(q
);
51 read_counter(struct fd_context
*ctx
, int type
)
54 case PIPE_QUERY_PRIMITIVES_GENERATED
:
55 return ctx
->stats
.prims_generated
;
56 case PIPE_QUERY_PRIMITIVES_EMITTED
:
57 return ctx
->stats
.prims_emitted
;
58 case FD_QUERY_DRAW_CALLS
:
59 return ctx
->stats
.draw_calls
;
60 case FD_QUERY_BATCH_TOTAL
:
61 return ctx
->stats
.batch_total
;
62 case FD_QUERY_BATCH_SYSMEM
:
63 return ctx
->stats
.batch_sysmem
;
64 case FD_QUERY_BATCH_GMEM
:
65 return ctx
->stats
.batch_gmem
;
66 case FD_QUERY_BATCH_NONDRAW
:
67 return ctx
->stats
.batch_nondraw
;
68 case FD_QUERY_BATCH_RESTORE
:
69 return ctx
->stats
.batch_restore
;
70 case FD_QUERY_STAGING_UPLOADS
:
71 return ctx
->stats
.staging_uploads
;
72 case FD_QUERY_SHADOW_UPLOADS
:
73 return ctx
->stats
.shadow_uploads
;
74 case FD_QUERY_VS_REGS
:
75 return ctx
->stats
.vs_regs
;
76 case FD_QUERY_FS_REGS
:
77 return ctx
->stats
.fs_regs
;
83 is_time_rate_query(struct fd_query
*q
)
86 case FD_QUERY_BATCH_TOTAL
:
87 case FD_QUERY_BATCH_SYSMEM
:
88 case FD_QUERY_BATCH_GMEM
:
89 case FD_QUERY_BATCH_NONDRAW
:
90 case FD_QUERY_BATCH_RESTORE
:
91 case FD_QUERY_STAGING_UPLOADS
:
92 case FD_QUERY_SHADOW_UPLOADS
:
100 is_draw_rate_query(struct fd_query
*q
)
103 case FD_QUERY_VS_REGS
:
104 case FD_QUERY_FS_REGS
:
112 fd_sw_begin_query(struct fd_context
*ctx
, struct fd_query
*q
)
114 struct fd_sw_query
*sq
= fd_sw_query(q
);
115 sq
->begin_value
= read_counter(ctx
, q
->type
);
116 if (is_time_rate_query(q
)) {
117 sq
->begin_time
= os_time_get();
118 } else if (is_draw_rate_query(q
)) {
119 sq
->begin_time
= ctx
->stats
.draw_calls
;
125 fd_sw_end_query(struct fd_context
*ctx
, struct fd_query
*q
)
127 struct fd_sw_query
*sq
= fd_sw_query(q
);
128 sq
->end_value
= read_counter(ctx
, q
->type
);
129 if (is_time_rate_query(q
)) {
130 sq
->end_time
= os_time_get();
131 } else if (is_draw_rate_query(q
)) {
132 sq
->end_time
= ctx
->stats
.draw_calls
;
137 fd_sw_get_query_result(struct fd_context
*ctx
, struct fd_query
*q
,
138 bool wait
, union pipe_query_result
*result
)
140 struct fd_sw_query
*sq
= fd_sw_query(q
);
142 result
->u64
= sq
->end_value
- sq
->begin_value
;
144 if (is_time_rate_query(q
)) {
145 double fps
= (result
->u64
* 1000000) /
146 (double)(sq
->end_time
- sq
->begin_time
);
147 result
->u64
= (uint64_t)fps
;
148 } else if (is_draw_rate_query(q
)) {
149 double avg
= ((double)result
->u64
) /
150 (double)(sq
->end_time
- sq
->begin_time
);
157 static const struct fd_query_funcs sw_query_funcs
= {
158 .destroy_query
= fd_sw_destroy_query
,
159 .begin_query
= fd_sw_begin_query
,
160 .end_query
= fd_sw_end_query
,
161 .get_query_result
= fd_sw_get_query_result
,
165 fd_sw_create_query(struct fd_context
*ctx
, unsigned query_type
, unsigned index
)
167 struct fd_sw_query
*sq
;
170 switch (query_type
) {
171 case PIPE_QUERY_PRIMITIVES_GENERATED
:
172 case PIPE_QUERY_PRIMITIVES_EMITTED
:
173 case FD_QUERY_DRAW_CALLS
:
174 case FD_QUERY_BATCH_TOTAL
:
175 case FD_QUERY_BATCH_SYSMEM
:
176 case FD_QUERY_BATCH_GMEM
:
177 case FD_QUERY_BATCH_NONDRAW
:
178 case FD_QUERY_BATCH_RESTORE
:
179 case FD_QUERY_STAGING_UPLOADS
:
180 case FD_QUERY_SHADOW_UPLOADS
:
181 case FD_QUERY_VS_REGS
:
182 case FD_QUERY_FS_REGS
:
188 sq
= CALLOC_STRUCT(fd_sw_query
);
193 q
->funcs
= &sw_query_funcs
;
194 q
->type
= query_type
;