radeonsi: dump init_config IBs
[mesa.git] / src / gallium / drivers / nouveau / nv50 / nv50_query_hw_metric.c
1 /*
2 * Copyright 2015 Samuel Pitoiset
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 shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23 #include "nv50/nv50_context.h"
24 #include "nv50/nv50_query_hw_metric.h"
25 #include "nv50/nv50_query_hw_sm.h"
26
27 /* === PERFORMANCE MONITORING METRICS for NV84+ === */
28 static const char *nv50_hw_metric_names[] =
29 {
30 "metric-branch_efficiency",
31 };
32
33 struct nv50_hw_metric_query_cfg {
34 uint32_t queries[4];
35 uint32_t num_queries;
36 };
37
38 #define _SM(n) NV50_HW_SM_QUERY(NV50_HW_SM_QUERY_ ##n)
39 #define _M(n, c) [NV50_HW_METRIC_QUERY_##n] = c
40
41 /* ==== Compute capability 1.1 (G84+) ==== */
42 static const struct nv50_hw_metric_query_cfg
43 sm11_branch_efficiency =
44 {
45 .queries[0] = _SM(BRANCH),
46 .queries[1] = _SM(DIVERGENT_BRANCH),
47 .num_queries = 2,
48 };
49
50 static const struct nv50_hw_metric_query_cfg *sm11_hw_metric_queries[] =
51 {
52 _M(BRANCH_EFFICIENCY, &sm11_branch_efficiency),
53 };
54
55 #undef _SM
56 #undef _M
57
58 static const struct nv50_hw_metric_query_cfg *
59 nv50_hw_metric_query_get_cfg(struct nv50_context *nv50,
60 struct nv50_hw_query *hq)
61 {
62 struct nv50_query *q = &hq->base;
63 return sm11_hw_metric_queries[q->type - NV50_HW_METRIC_QUERY(0)];
64 }
65
66 static void
67 nv50_hw_metric_destroy_query(struct nv50_context *nv50,
68 struct nv50_hw_query *hq)
69 {
70 struct nv50_hw_metric_query *hmq = nv50_hw_metric_query(hq);
71 unsigned i;
72
73 for (i = 0; i < hmq->num_queries; i++)
74 hmq->queries[i]->funcs->destroy_query(nv50, hmq->queries[i]);
75 FREE(hmq);
76 }
77
78 static boolean
79 nv50_hw_metric_begin_query(struct nv50_context *nv50, struct nv50_hw_query *hq)
80 {
81 struct nv50_hw_metric_query *hmq = nv50_hw_metric_query(hq);
82 boolean ret = false;
83 unsigned i;
84
85 for (i = 0; i < hmq->num_queries; i++) {
86 ret = hmq->queries[i]->funcs->begin_query(nv50, hmq->queries[i]);
87 if (!ret)
88 return ret;
89 }
90 return ret;
91 }
92
93 static void
94 nv50_hw_metric_end_query(struct nv50_context *nv50, struct nv50_hw_query *hq)
95 {
96 struct nv50_hw_metric_query *hmq = nv50_hw_metric_query(hq);
97 unsigned i;
98
99 for (i = 0; i < hmq->num_queries; i++)
100 hmq->queries[i]->funcs->end_query(nv50, hmq->queries[i]);
101 }
102
103 static uint64_t
104 sm11_hw_metric_calc_result(struct nv50_hw_query *hq, uint64_t res64[8])
105 {
106 switch (hq->base.type - NV50_HW_METRIC_QUERY(0)) {
107 case NV50_HW_METRIC_QUERY_BRANCH_EFFICIENCY:
108 /* (branch / (branch + divergent_branch)) * 100 */
109 if (res64[0] + res64[1])
110 return (res64[0] / (double)(res64[0] + res64[1])) * 100;
111 break;
112 default:
113 debug_printf("invalid metric type: %d\n",
114 hq->base.type - NV50_HW_METRIC_QUERY(0));
115 break;
116 }
117 return 0;
118 }
119
120 static boolean
121 nv50_hw_metric_get_query_result(struct nv50_context *nv50,
122 struct nv50_hw_query *hq, boolean wait,
123 union pipe_query_result *result)
124 {
125 struct nv50_hw_metric_query *hmq = nv50_hw_metric_query(hq);
126 union pipe_query_result results[4] = {};
127 uint64_t res64[4] = {};
128 boolean ret = false;
129 unsigned i;
130
131 for (i = 0; i < hmq->num_queries; i++) {
132 ret = hmq->queries[i]->funcs->get_query_result(nv50, hmq->queries[i],
133 wait, &results[i]);
134 if (!ret)
135 return ret;
136 res64[i] = *(uint64_t *)&results[i];
137 }
138
139 *(uint64_t *)result = sm11_hw_metric_calc_result(hq, res64);
140 return ret;
141 }
142
143 static const struct nv50_hw_query_funcs hw_metric_query_funcs = {
144 .destroy_query = nv50_hw_metric_destroy_query,
145 .begin_query = nv50_hw_metric_begin_query,
146 .end_query = nv50_hw_metric_end_query,
147 .get_query_result = nv50_hw_metric_get_query_result,
148 };
149
150 struct nv50_hw_query *
151 nv50_hw_metric_create_query(struct nv50_context *nv50, unsigned type)
152 {
153 const struct nv50_hw_metric_query_cfg *cfg;
154 struct nv50_hw_metric_query *hmq;
155 struct nv50_hw_query *hq;
156 unsigned i;
157
158 if (type < NV50_HW_METRIC_QUERY(0) || type > NV50_HW_METRIC_QUERY_LAST)
159 return NULL;
160
161 hmq = CALLOC_STRUCT(nv50_hw_metric_query);
162 if (!hmq)
163 return NULL;
164
165 hq = &hmq->base;
166 hq->funcs = &hw_metric_query_funcs;
167 hq->base.type = type;
168
169 cfg = nv50_hw_metric_query_get_cfg(nv50, hq);
170
171 for (i = 0; i < cfg->num_queries; i++) {
172 hmq->queries[i] = nv50_hw_sm_create_query(nv50, cfg->queries[i]);
173 if (!hmq->queries[i]) {
174 nv50_hw_metric_destroy_query(nv50, hq);
175 return NULL;
176 }
177 hmq->num_queries++;
178 }
179
180 return hq;
181 }
182
183 int
184 nv50_hw_metric_get_driver_query_info(struct nv50_screen *screen, unsigned id,
185 struct pipe_driver_query_info *info)
186 {
187 int count = 0;
188
189 if (screen->compute)
190 if (screen->base.class_3d >= NV84_3D_CLASS)
191 count += NV50_HW_METRIC_QUERY_COUNT;
192
193 if (!info)
194 return count;
195
196 if (id < count) {
197 if (screen->compute) {
198 if (screen->base.class_3d >= NV84_3D_CLASS) {
199 info->name = nv50_hw_metric_names[id];
200 info->query_type = NV50_HW_METRIC_QUERY(id);
201 info->group_id = NV50_HW_METRIC_QUERY_GROUP;
202 return 1;
203 }
204 }
205 }
206 return 0;
207 }