1/* 2 * Copyright (C) 2013 Rob Clark <robclark@freedesktop.org> 3 * 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: 10 * 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 13 * Software. 14 * 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 21 * SOFTWARE. 22 * 23 * Authors: 24 * Rob Clark <robclark@freedesktop.org> 25 */ 26 27#include "pipe/p_state.h" 28#include "util/u_memory.h" 29 30#include "freedreno_query.h" 31#include "freedreno_query_sw.h" 32#include "freedreno_query_hw.h" 33#include "freedreno_context.h" 34#include "freedreno_util.h" 35 36/* 37 * Pipe Query interface: 38 */ 39 40static struct pipe_query * 41fd_create_query(struct pipe_context *pctx, unsigned query_type, unsigned index) 42{ 43 struct fd_context *ctx = fd_context(pctx); 44 struct fd_query *q; 45 46 q = fd_sw_create_query(ctx, query_type); 47 if (!q && ctx->create_query) 48 q = ctx->create_query(ctx, query_type); 49 50 return (struct pipe_query *) q; 51} 52 53static void 54fd_destroy_query(struct pipe_context *pctx, struct pipe_query *pq) 55{ 56 struct fd_query *q = fd_query(pq); 57 q->funcs->destroy_query(fd_context(pctx), q); 58} 59 60static boolean 61fd_begin_query(struct pipe_context *pctx, struct pipe_query *pq) 62{ 63 struct fd_query *q = fd_query(pq); 64 boolean ret; 65 66 if (q->active) 67 return false; 68 69 ret = q->funcs->begin_query(fd_context(pctx), q); 70 q->active = ret; 71 72 return ret; 73} 74 75static bool 76fd_end_query(struct pipe_context *pctx, struct pipe_query *pq) 77{ 78 struct fd_query *q = fd_query(pq); 79 80 /* there are a couple special cases, which don't have 81 * a matching ->begin_query(): 82 */ 83 if (skip_begin_query(q->type) && !q->active) 84 fd_begin_query(pctx, pq); 85 86 if (!q->active) 87 return false; 88 89 q->funcs->end_query(fd_context(pctx), q); 90 q->active = false; 91 92 return true; 93} 94 95static boolean 96fd_get_query_result(struct pipe_context *pctx, struct pipe_query *pq, 97 boolean wait, union pipe_query_result *result) 98{ 99 struct fd_query *q = fd_query(pq); 100 101 if (q->active) 102 return false; 103 104 util_query_clear_result(result, q->type); 105 106 return q->funcs->get_query_result(fd_context(pctx), q, wait, result); 107} 108 109static void 110fd_render_condition(struct pipe_context *pctx, struct pipe_query *pq, 111 boolean condition, enum pipe_render_cond_flag mode) 112{ 113 struct fd_context *ctx = fd_context(pctx); 114 ctx->cond_query = pq; 115 ctx->cond_cond = condition; 116 ctx->cond_mode = mode; 117} 118 119#define _Q(_name, _query_type, _type, _result_type) { \ 120 .name = _name, \ 121 .query_type = _query_type, \ 122 .type = PIPE_DRIVER_QUERY_TYPE_ ## _type, \ 123 .result_type = PIPE_DRIVER_QUERY_RESULT_TYPE_ ## _result_type, \ 124 .group_id = ~(unsigned)0, \ 125} 126 127#define FQ(_name, _query_type, _type, _result_type) \ 128 _Q(_name, FD_QUERY_ ## _query_type, _type, _result_type) 129 130#define PQ(_name, _query_type, _type, _result_type) \ 131 _Q(_name, PIPE_QUERY_ ## _query_type, _type, _result_type) 132 133static const struct pipe_driver_query_info sw_query_list[] = { 134 FQ("draw-calls", DRAW_CALLS, UINT64, AVERAGE), 135 FQ("batches", BATCH_TOTAL, UINT64, AVERAGE), 136 FQ("batches-sysmem", BATCH_SYSMEM, UINT64, AVERAGE), 137 FQ("batches-gmem", BATCH_GMEM, UINT64, AVERAGE), 138 FQ("batches-nondraw", BATCH_NONDRAW, UINT64, AVERAGE), 139 FQ("restores", BATCH_RESTORE, UINT64, AVERAGE), 140 PQ("prims-emitted", PRIMITIVES_EMITTED, UINT64, AVERAGE), 141 FQ("staging", STAGING_UPLOADS, UINT64, AVERAGE), 142 FQ("shadow", SHADOW_UPLOADS, UINT64, AVERAGE), 143 FQ("vsregs", VS_REGS, FLOAT, AVERAGE), 144 FQ("fsregs", FS_REGS, FLOAT, AVERAGE), 145}; 146 147static int 148fd_get_driver_query_info(struct pipe_screen *pscreen, 149 unsigned index, struct pipe_driver_query_info *info) 150{ 151 struct fd_screen *screen = fd_screen(pscreen); 152 153 if (!info) 154 return ARRAY_SIZE(sw_query_list) + screen->num_perfcntr_queries; 155 156 if (index >= ARRAY_SIZE(sw_query_list)) { 157 index -= ARRAY_SIZE(sw_query_list); 158 if (index >= screen->num_perfcntr_queries) 159 return 0; 160 *info = screen->perfcntr_queries[index]; 161 return 1; 162 } 163 164 *info = sw_query_list[index]; 165 return 1; 166} 167 168static int 169fd_get_driver_query_group_info(struct pipe_screen *pscreen, unsigned index, 170 struct pipe_driver_query_group_info *info) 171{ 172 struct fd_screen *screen = fd_screen(pscreen); 173 174 if (!info) 175 return screen->num_perfcntr_groups; 176 177 if (index >= screen->num_perfcntr_groups) 178 return 0; 179 180 const struct fd_perfcntr_group *g = &screen->perfcntr_groups[index]; 181 182 info->name = g->name; 183 info->max_active_queries = g->num_counters; 184 info->num_queries = g->num_countables; 185 186 return 1; 187} 188 189static void 190fd_set_active_query_state(struct pipe_context *pipe, boolean enable) 191{ 192} 193 194static void 195setup_perfcntr_query_info(struct fd_screen *screen) 196{ 197 unsigned num_queries = 0; 198 199 for (unsigned i = 0; i < screen->num_perfcntr_groups; i++) 200 num_queries += screen->perfcntr_groups[i].num_countables; 201 202 screen->perfcntr_queries = 203 calloc(num_queries, sizeof(screen->perfcntr_queries[0])); 204 screen->num_perfcntr_queries = num_queries; 205 206 unsigned idx = 0; 207 for (unsigned i = 0; i < screen->num_perfcntr_groups; i++) { 208 const struct fd_perfcntr_group *g = &screen->perfcntr_groups[i]; 209 for (unsigned j = 0; j < g->num_countables; j++) { 210 struct pipe_driver_query_info *info = 211 &screen->perfcntr_queries[idx]; 212 const struct fd_perfcntr_countable *c = 213 &g->countables[j]; 214 215 info->name = c->name; 216 info->query_type = FD_QUERY_FIRST_PERFCNTR + idx; 217 info->type = c->query_type; 218 info->result_type = c->result_type; 219 info->group_id = i; 220 info->flags = PIPE_DRIVER_QUERY_FLAG_BATCH; 221 222 idx++; 223 } 224 } 225} 226 227void 228fd_query_screen_init(struct pipe_screen *pscreen) 229{ 230 pscreen->get_driver_query_info = fd_get_driver_query_info; 231 pscreen->get_driver_query_group_info = fd_get_driver_query_group_info; 232 setup_perfcntr_query_info(fd_screen(pscreen)); 233} 234 235void 236fd_query_context_init(struct pipe_context *pctx) 237{ 238 pctx->create_query = fd_create_query; 239 pctx->destroy_query = fd_destroy_query; 240 pctx->begin_query = fd_begin_query; 241 pctx->end_query = fd_end_query; 242 pctx->get_query_result = fd_get_query_result; 243 pctx->set_active_query_state = fd_set_active_query_state; 244 pctx->render_condition = fd_render_condition; 245} 246