Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/nouveau/nv50/nv50_query_hw_metric.c
4574 views
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
if (hmq->queries[i]->funcs->destroy_query)
75
hmq->queries[i]->funcs->destroy_query(nv50, hmq->queries[i]);
76
FREE(hmq);
77
}
78
79
static bool
80
nv50_hw_metric_begin_query(struct nv50_context *nv50, struct nv50_hw_query *hq)
81
{
82
struct nv50_hw_metric_query *hmq = nv50_hw_metric_query(hq);
83
bool ret = false;
84
unsigned i;
85
86
for (i = 0; i < hmq->num_queries; i++) {
87
ret = hmq->queries[i]->funcs->begin_query(nv50, hmq->queries[i]);
88
if (!ret)
89
return ret;
90
}
91
return ret;
92
}
93
94
static void
95
nv50_hw_metric_end_query(struct nv50_context *nv50, struct nv50_hw_query *hq)
96
{
97
struct nv50_hw_metric_query *hmq = nv50_hw_metric_query(hq);
98
unsigned i;
99
100
for (i = 0; i < hmq->num_queries; i++)
101
hmq->queries[i]->funcs->end_query(nv50, hmq->queries[i]);
102
}
103
104
static uint64_t
105
sm11_hw_metric_calc_result(struct nv50_hw_query *hq, uint64_t res64[4])
106
{
107
switch (hq->base.type - NV50_HW_METRIC_QUERY(0)) {
108
case NV50_HW_METRIC_QUERY_BRANCH_EFFICIENCY:
109
/* (branch / (branch + divergent_branch)) * 100 */
110
if (res64[0] + res64[1])
111
return (res64[0] / (double)(res64[0] + res64[1])) * 100;
112
break;
113
default:
114
debug_printf("invalid metric type: %d\n",
115
hq->base.type - NV50_HW_METRIC_QUERY(0));
116
break;
117
}
118
return 0;
119
}
120
121
static bool
122
nv50_hw_metric_get_query_result(struct nv50_context *nv50,
123
struct nv50_hw_query *hq, bool wait,
124
union pipe_query_result *result)
125
{
126
struct nv50_hw_metric_query *hmq = nv50_hw_metric_query(hq);
127
union pipe_query_result results[4] = {};
128
uint64_t res64[4] = {};
129
bool ret = false;
130
unsigned i;
131
132
for (i = 0; i < hmq->num_queries; i++) {
133
ret = hmq->queries[i]->funcs->get_query_result(nv50, hmq->queries[i],
134
wait, &results[i]);
135
if (!ret)
136
return ret;
137
res64[i] = *(uint64_t *)&results[i];
138
}
139
140
*(uint64_t *)result = sm11_hw_metric_calc_result(hq, res64);
141
return ret;
142
}
143
144
static const struct nv50_hw_query_funcs hw_metric_query_funcs = {
145
.destroy_query = nv50_hw_metric_destroy_query,
146
.begin_query = nv50_hw_metric_begin_query,
147
.end_query = nv50_hw_metric_end_query,
148
.get_query_result = nv50_hw_metric_get_query_result,
149
};
150
151
struct nv50_hw_query *
152
nv50_hw_metric_create_query(struct nv50_context *nv50, unsigned type)
153
{
154
const struct nv50_hw_metric_query_cfg *cfg;
155
struct nv50_hw_metric_query *hmq;
156
struct nv50_hw_query *hq;
157
unsigned i;
158
159
if (type < NV50_HW_METRIC_QUERY(0) || type > NV50_HW_METRIC_QUERY_LAST)
160
return NULL;
161
162
hmq = CALLOC_STRUCT(nv50_hw_metric_query);
163
if (!hmq)
164
return NULL;
165
166
hq = &hmq->base;
167
hq->funcs = &hw_metric_query_funcs;
168
hq->base.type = type;
169
170
cfg = nv50_hw_metric_query_get_cfg(nv50, hq);
171
172
for (i = 0; i < cfg->num_queries; i++) {
173
hmq->queries[i] = nv50_hw_sm_create_query(nv50, cfg->queries[i]);
174
if (!hmq->queries[i]) {
175
nv50_hw_metric_destroy_query(nv50, hq);
176
return NULL;
177
}
178
hmq->num_queries++;
179
}
180
181
return hq;
182
}
183
184
int
185
nv50_hw_metric_get_driver_query_info(struct nv50_screen *screen, unsigned id,
186
struct pipe_driver_query_info *info)
187
{
188
int count = 0;
189
190
if (screen->compute)
191
if (screen->base.class_3d >= NV84_3D_CLASS)
192
count += NV50_HW_METRIC_QUERY_COUNT;
193
194
if (!info)
195
return count;
196
197
if (id < count) {
198
if (screen->compute) {
199
if (screen->base.class_3d >= NV84_3D_CLASS) {
200
info->name = nv50_hw_metric_names[id];
201
info->query_type = NV50_HW_METRIC_QUERY(id);
202
info->group_id = NV50_HW_METRIC_QUERY_GROUP;
203
return 1;
204
}
205
}
206
}
207
return 0;
208
}
209
210