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