1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21bf215546Sopenharmony_ci * SOFTWARE.
22bf215546Sopenharmony_ci *
23bf215546Sopenharmony_ci * Authors:
24bf215546Sopenharmony_ci *    Rob Clark <robclark@freedesktop.org>
25bf215546Sopenharmony_ci */
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "pipe/p_state.h"
28bf215546Sopenharmony_ci#include "util/os_time.h"
29bf215546Sopenharmony_ci#include "util/u_inlines.h"
30bf215546Sopenharmony_ci#include "util/u_memory.h"
31bf215546Sopenharmony_ci#include "util/u_string.h"
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ci#include "freedreno_context.h"
34bf215546Sopenharmony_ci#include "freedreno_query_sw.h"
35bf215546Sopenharmony_ci#include "freedreno_util.h"
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci/*
38bf215546Sopenharmony_ci * SW Queries:
39bf215546Sopenharmony_ci *
40bf215546Sopenharmony_ci * In the core, we have some support for basic sw counters
41bf215546Sopenharmony_ci */
42bf215546Sopenharmony_ci
43bf215546Sopenharmony_cistatic void
44bf215546Sopenharmony_cifd_sw_destroy_query(struct fd_context *ctx, struct fd_query *q)
45bf215546Sopenharmony_ci{
46bf215546Sopenharmony_ci   struct fd_sw_query *sq = fd_sw_query(q);
47bf215546Sopenharmony_ci   free(sq);
48bf215546Sopenharmony_ci}
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_cistatic uint64_t
51bf215546Sopenharmony_ciread_counter(struct fd_context *ctx, int type) assert_dt
52bf215546Sopenharmony_ci{
53bf215546Sopenharmony_ci   switch (type) {
54bf215546Sopenharmony_ci   case PIPE_QUERY_PRIMITIVES_GENERATED:
55bf215546Sopenharmony_ci      return ctx->stats.prims_generated;
56bf215546Sopenharmony_ci   case PIPE_QUERY_PRIMITIVES_EMITTED:
57bf215546Sopenharmony_ci      return ctx->stats.prims_emitted;
58bf215546Sopenharmony_ci   case FD_QUERY_DRAW_CALLS:
59bf215546Sopenharmony_ci      return ctx->stats.draw_calls;
60bf215546Sopenharmony_ci   case FD_QUERY_BATCH_TOTAL:
61bf215546Sopenharmony_ci      return ctx->stats.batch_total;
62bf215546Sopenharmony_ci   case FD_QUERY_BATCH_SYSMEM:
63bf215546Sopenharmony_ci      return ctx->stats.batch_sysmem;
64bf215546Sopenharmony_ci   case FD_QUERY_BATCH_GMEM:
65bf215546Sopenharmony_ci      return ctx->stats.batch_gmem;
66bf215546Sopenharmony_ci   case FD_QUERY_BATCH_NONDRAW:
67bf215546Sopenharmony_ci      return ctx->stats.batch_nondraw;
68bf215546Sopenharmony_ci   case FD_QUERY_BATCH_RESTORE:
69bf215546Sopenharmony_ci      return ctx->stats.batch_restore;
70bf215546Sopenharmony_ci   case FD_QUERY_STAGING_UPLOADS:
71bf215546Sopenharmony_ci      return ctx->stats.staging_uploads;
72bf215546Sopenharmony_ci   case FD_QUERY_SHADOW_UPLOADS:
73bf215546Sopenharmony_ci      return ctx->stats.shadow_uploads;
74bf215546Sopenharmony_ci   case FD_QUERY_VS_REGS:
75bf215546Sopenharmony_ci      return ctx->stats.vs_regs;
76bf215546Sopenharmony_ci   case FD_QUERY_FS_REGS:
77bf215546Sopenharmony_ci      return ctx->stats.fs_regs;
78bf215546Sopenharmony_ci   }
79bf215546Sopenharmony_ci   return 0;
80bf215546Sopenharmony_ci}
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_cistatic bool
83bf215546Sopenharmony_ciis_time_rate_query(struct fd_query *q)
84bf215546Sopenharmony_ci{
85bf215546Sopenharmony_ci   switch (q->type) {
86bf215546Sopenharmony_ci   case FD_QUERY_BATCH_TOTAL:
87bf215546Sopenharmony_ci   case FD_QUERY_BATCH_SYSMEM:
88bf215546Sopenharmony_ci   case FD_QUERY_BATCH_GMEM:
89bf215546Sopenharmony_ci   case FD_QUERY_BATCH_NONDRAW:
90bf215546Sopenharmony_ci   case FD_QUERY_BATCH_RESTORE:
91bf215546Sopenharmony_ci   case FD_QUERY_STAGING_UPLOADS:
92bf215546Sopenharmony_ci   case FD_QUERY_SHADOW_UPLOADS:
93bf215546Sopenharmony_ci      return true;
94bf215546Sopenharmony_ci   default:
95bf215546Sopenharmony_ci      return false;
96bf215546Sopenharmony_ci   }
97bf215546Sopenharmony_ci}
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_cistatic bool
100bf215546Sopenharmony_ciis_draw_rate_query(struct fd_query *q)
101bf215546Sopenharmony_ci{
102bf215546Sopenharmony_ci   switch (q->type) {
103bf215546Sopenharmony_ci   case FD_QUERY_VS_REGS:
104bf215546Sopenharmony_ci   case FD_QUERY_FS_REGS:
105bf215546Sopenharmony_ci      return true;
106bf215546Sopenharmony_ci   default:
107bf215546Sopenharmony_ci      return false;
108bf215546Sopenharmony_ci   }
109bf215546Sopenharmony_ci}
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_cistatic void
112bf215546Sopenharmony_cifd_sw_begin_query(struct fd_context *ctx, struct fd_query *q) assert_dt
113bf215546Sopenharmony_ci{
114bf215546Sopenharmony_ci   struct fd_sw_query *sq = fd_sw_query(q);
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ci   ctx->stats_users++;
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_ci   sq->begin_value = read_counter(ctx, q->type);
119bf215546Sopenharmony_ci   if (is_time_rate_query(q)) {
120bf215546Sopenharmony_ci      sq->begin_time = os_time_get();
121bf215546Sopenharmony_ci   } else if (is_draw_rate_query(q)) {
122bf215546Sopenharmony_ci      sq->begin_time = ctx->stats.draw_calls;
123bf215546Sopenharmony_ci   }
124bf215546Sopenharmony_ci}
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_cistatic void
127bf215546Sopenharmony_cifd_sw_end_query(struct fd_context *ctx, struct fd_query *q) assert_dt
128bf215546Sopenharmony_ci{
129bf215546Sopenharmony_ci   struct fd_sw_query *sq = fd_sw_query(q);
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_ci   assert(ctx->stats_users > 0);
132bf215546Sopenharmony_ci   ctx->stats_users--;
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci   sq->end_value = read_counter(ctx, q->type);
135bf215546Sopenharmony_ci   if (is_time_rate_query(q)) {
136bf215546Sopenharmony_ci      sq->end_time = os_time_get();
137bf215546Sopenharmony_ci   } else if (is_draw_rate_query(q)) {
138bf215546Sopenharmony_ci      sq->end_time = ctx->stats.draw_calls;
139bf215546Sopenharmony_ci   }
140bf215546Sopenharmony_ci}
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_cistatic bool
143bf215546Sopenharmony_cifd_sw_get_query_result(struct fd_context *ctx, struct fd_query *q, bool wait,
144bf215546Sopenharmony_ci                       union pipe_query_result *result)
145bf215546Sopenharmony_ci{
146bf215546Sopenharmony_ci   struct fd_sw_query *sq = fd_sw_query(q);
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_ci   result->u64 = sq->end_value - sq->begin_value;
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci   if (is_time_rate_query(q)) {
151bf215546Sopenharmony_ci      double fps =
152bf215546Sopenharmony_ci         (result->u64 * 1000000) / (double)(sq->end_time - sq->begin_time);
153bf215546Sopenharmony_ci      result->u64 = (uint64_t)fps;
154bf215546Sopenharmony_ci   } else if (is_draw_rate_query(q)) {
155bf215546Sopenharmony_ci      double avg =
156bf215546Sopenharmony_ci         ((double)result->u64) / (double)(sq->end_time - sq->begin_time);
157bf215546Sopenharmony_ci      result->f = avg;
158bf215546Sopenharmony_ci   }
159bf215546Sopenharmony_ci
160bf215546Sopenharmony_ci   return true;
161bf215546Sopenharmony_ci}
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_cistatic const struct fd_query_funcs sw_query_funcs = {
164bf215546Sopenharmony_ci   .destroy_query = fd_sw_destroy_query,
165bf215546Sopenharmony_ci   .begin_query = fd_sw_begin_query,
166bf215546Sopenharmony_ci   .end_query = fd_sw_end_query,
167bf215546Sopenharmony_ci   .get_query_result = fd_sw_get_query_result,
168bf215546Sopenharmony_ci};
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_cistruct fd_query *
171bf215546Sopenharmony_cifd_sw_create_query(struct fd_context *ctx, unsigned query_type, unsigned index)
172bf215546Sopenharmony_ci{
173bf215546Sopenharmony_ci   struct fd_sw_query *sq;
174bf215546Sopenharmony_ci   struct fd_query *q;
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci   switch (query_type) {
177bf215546Sopenharmony_ci   case PIPE_QUERY_PRIMITIVES_GENERATED:
178bf215546Sopenharmony_ci   case PIPE_QUERY_PRIMITIVES_EMITTED:
179bf215546Sopenharmony_ci   case FD_QUERY_DRAW_CALLS:
180bf215546Sopenharmony_ci   case FD_QUERY_BATCH_TOTAL:
181bf215546Sopenharmony_ci   case FD_QUERY_BATCH_SYSMEM:
182bf215546Sopenharmony_ci   case FD_QUERY_BATCH_GMEM:
183bf215546Sopenharmony_ci   case FD_QUERY_BATCH_NONDRAW:
184bf215546Sopenharmony_ci   case FD_QUERY_BATCH_RESTORE:
185bf215546Sopenharmony_ci   case FD_QUERY_STAGING_UPLOADS:
186bf215546Sopenharmony_ci   case FD_QUERY_SHADOW_UPLOADS:
187bf215546Sopenharmony_ci   case FD_QUERY_VS_REGS:
188bf215546Sopenharmony_ci   case FD_QUERY_FS_REGS:
189bf215546Sopenharmony_ci      break;
190bf215546Sopenharmony_ci   default:
191bf215546Sopenharmony_ci      return NULL;
192bf215546Sopenharmony_ci   }
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci   sq = CALLOC_STRUCT(fd_sw_query);
195bf215546Sopenharmony_ci   if (!sq)
196bf215546Sopenharmony_ci      return NULL;
197bf215546Sopenharmony_ci
198bf215546Sopenharmony_ci   q = &sq->base;
199bf215546Sopenharmony_ci   q->funcs = &sw_query_funcs;
200bf215546Sopenharmony_ci   q->type = query_type;
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ci   return q;
203bf215546Sopenharmony_ci}
204