xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/freedreno/freedreno_query_sw.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2014 Rob Clark <[email protected]>
3  * SPDX-License-Identifier: MIT
4  *
5  * Authors:
6  *    Rob Clark <[email protected]>
7  */
8 
9 #include "pipe/p_state.h"
10 #include "util/os_time.h"
11 #include "util/u_inlines.h"
12 #include "util/u_memory.h"
13 #include "util/u_string.h"
14 
15 #include "freedreno_context.h"
16 #include "freedreno_query_sw.h"
17 #include "freedreno_util.h"
18 
19 /*
20  * SW Queries:
21  *
22  * In the core, we have some support for basic sw counters
23  */
24 
25 static void
fd_sw_destroy_query(struct fd_context * ctx,struct fd_query * q)26 fd_sw_destroy_query(struct fd_context *ctx, struct fd_query *q)
27 {
28    struct fd_sw_query *sq = fd_sw_query(q);
29    free(sq);
30 }
31 
32 static uint64_t
read_counter(struct fd_context * ctx,int type)33 read_counter(struct fd_context *ctx, int type) assert_dt
34 {
35    switch (type) {
36    case PIPE_QUERY_PRIMITIVES_GENERATED:
37       return ctx->stats.prims_generated;
38    case PIPE_QUERY_PRIMITIVES_EMITTED:
39       return ctx->stats.prims_emitted;
40    case FD_QUERY_DRAW_CALLS:
41       return ctx->stats.draw_calls;
42    case FD_QUERY_BATCH_TOTAL:
43       return ctx->stats.batch_total;
44    case FD_QUERY_BATCH_SYSMEM:
45       return ctx->stats.batch_sysmem;
46    case FD_QUERY_BATCH_GMEM:
47       return ctx->stats.batch_gmem;
48    case FD_QUERY_BATCH_NONDRAW:
49       return ctx->stats.batch_nondraw;
50    case FD_QUERY_BATCH_RESTORE:
51       return ctx->stats.batch_restore;
52    case FD_QUERY_STAGING_UPLOADS:
53       return ctx->stats.staging_uploads;
54    case FD_QUERY_SHADOW_UPLOADS:
55       return ctx->stats.shadow_uploads;
56    case FD_QUERY_VS_REGS:
57       return ctx->stats.vs_regs;
58    case FD_QUERY_FS_REGS:
59       return ctx->stats.fs_regs;
60    }
61    return 0;
62 }
63 
64 static bool
is_time_rate_query(struct fd_query * q)65 is_time_rate_query(struct fd_query *q)
66 {
67    switch (q->type) {
68    case FD_QUERY_BATCH_TOTAL:
69    case FD_QUERY_BATCH_SYSMEM:
70    case FD_QUERY_BATCH_GMEM:
71    case FD_QUERY_BATCH_NONDRAW:
72    case FD_QUERY_BATCH_RESTORE:
73    case FD_QUERY_STAGING_UPLOADS:
74    case FD_QUERY_SHADOW_UPLOADS:
75       return true;
76    default:
77       return false;
78    }
79 }
80 
81 static bool
is_draw_rate_query(struct fd_query * q)82 is_draw_rate_query(struct fd_query *q)
83 {
84    switch (q->type) {
85    case FD_QUERY_VS_REGS:
86    case FD_QUERY_FS_REGS:
87       return true;
88    default:
89       return false;
90    }
91 }
92 
93 static void
fd_sw_begin_query(struct fd_context * ctx,struct fd_query * q)94 fd_sw_begin_query(struct fd_context *ctx, struct fd_query *q) assert_dt
95 {
96    struct fd_sw_query *sq = fd_sw_query(q);
97 
98    ctx->stats_users++;
99 
100    sq->begin_value = read_counter(ctx, q->type);
101    if (is_time_rate_query(q)) {
102       sq->begin_time = os_time_get();
103    } else if (is_draw_rate_query(q)) {
104       sq->begin_time = ctx->stats.draw_calls;
105    }
106 }
107 
108 static void
fd_sw_end_query(struct fd_context * ctx,struct fd_query * q)109 fd_sw_end_query(struct fd_context *ctx, struct fd_query *q) assert_dt
110 {
111    struct fd_sw_query *sq = fd_sw_query(q);
112 
113    assert(ctx->stats_users > 0);
114    ctx->stats_users--;
115 
116    sq->end_value = read_counter(ctx, q->type);
117    if (is_time_rate_query(q)) {
118       sq->end_time = os_time_get();
119    } else if (is_draw_rate_query(q)) {
120       sq->end_time = ctx->stats.draw_calls;
121    }
122 }
123 
124 static bool
fd_sw_get_query_result(struct fd_context * ctx,struct fd_query * q,bool wait,union pipe_query_result * result)125 fd_sw_get_query_result(struct fd_context *ctx, struct fd_query *q, bool wait,
126                        union pipe_query_result *result)
127 {
128    struct fd_sw_query *sq = fd_sw_query(q);
129 
130    result->u64 = sq->end_value - sq->begin_value;
131 
132    if (is_time_rate_query(q)) {
133       double fps =
134          (result->u64 * 1000000) / (double)(sq->end_time - sq->begin_time);
135       result->u64 = (uint64_t)fps;
136    } else if (is_draw_rate_query(q)) {
137       double avg =
138          ((double)result->u64) / (double)(sq->end_time - sq->begin_time);
139       result->f = avg;
140    }
141 
142    return true;
143 }
144 
145 static const struct fd_query_funcs sw_query_funcs = {
146    .destroy_query = fd_sw_destroy_query,
147    .begin_query = fd_sw_begin_query,
148    .end_query = fd_sw_end_query,
149    .get_query_result = fd_sw_get_query_result,
150 };
151 
152 struct fd_query *
fd_sw_create_query(struct fd_context * ctx,unsigned query_type,unsigned index)153 fd_sw_create_query(struct fd_context *ctx, unsigned query_type, unsigned index)
154 {
155    struct fd_sw_query *sq;
156    struct fd_query *q;
157 
158    switch (query_type) {
159    case PIPE_QUERY_PRIMITIVES_GENERATED:
160    case PIPE_QUERY_PRIMITIVES_EMITTED:
161    case FD_QUERY_DRAW_CALLS:
162    case FD_QUERY_BATCH_TOTAL:
163    case FD_QUERY_BATCH_SYSMEM:
164    case FD_QUERY_BATCH_GMEM:
165    case FD_QUERY_BATCH_NONDRAW:
166    case FD_QUERY_BATCH_RESTORE:
167    case FD_QUERY_STAGING_UPLOADS:
168    case FD_QUERY_SHADOW_UPLOADS:
169    case FD_QUERY_VS_REGS:
170    case FD_QUERY_FS_REGS:
171       break;
172    default:
173       return NULL;
174    }
175 
176    sq = CALLOC_STRUCT(fd_sw_query);
177    if (!sq)
178       return NULL;
179 
180    q = &sq->base;
181    q->funcs = &sw_query_funcs;
182    q->type = query_type;
183 
184    return q;
185 }
186