2 * Copyright 2015 Samuel Pitoiset
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
23 #include "nv50/nv50_context.h"
24 #include "nv50/nv50_query_hw_metric.h"
25 #include "nv50/nv50_query_hw_sm.h"
27 /* === PERFORMANCE MONITORING METRICS for NV84+ === */
28 static const char *nv50_hw_metric_names
[] =
30 "metric-branch_efficiency",
33 struct nv50_hw_metric_query_cfg
{
38 #define _SM(n) NV50_HW_SM_QUERY(NV50_HW_SM_QUERY_ ##n)
39 #define _M(n, c) [NV50_HW_METRIC_QUERY_##n] = c
41 /* ==== Compute capability 1.1 (G84+) ==== */
42 static const struct nv50_hw_metric_query_cfg
43 sm11_branch_efficiency
=
45 .queries
[0] = _SM(BRANCH
),
46 .queries
[1] = _SM(DIVERGENT_BRANCH
),
50 static const struct nv50_hw_metric_query_cfg
*sm11_hw_metric_queries
[] =
52 _M(BRANCH_EFFICIENCY
, &sm11_branch_efficiency
),
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
)
62 struct nv50_query
*q
= &hq
->base
;
63 return sm11_hw_metric_queries
[q
->type
- NV50_HW_METRIC_QUERY(0)];
67 nv50_hw_metric_destroy_query(struct nv50_context
*nv50
,
68 struct nv50_hw_query
*hq
)
70 struct nv50_hw_metric_query
*hmq
= nv50_hw_metric_query(hq
);
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
]);
80 nv50_hw_metric_begin_query(struct nv50_context
*nv50
, struct nv50_hw_query
*hq
)
82 struct nv50_hw_metric_query
*hmq
= nv50_hw_metric_query(hq
);
86 for (i
= 0; i
< hmq
->num_queries
; i
++) {
87 ret
= hmq
->queries
[i
]->funcs
->begin_query(nv50
, hmq
->queries
[i
]);
95 nv50_hw_metric_end_query(struct nv50_context
*nv50
, struct nv50_hw_query
*hq
)
97 struct nv50_hw_metric_query
*hmq
= nv50_hw_metric_query(hq
);
100 for (i
= 0; i
< hmq
->num_queries
; i
++)
101 hmq
->queries
[i
]->funcs
->end_query(nv50
, hmq
->queries
[i
]);
105 sm11_hw_metric_calc_result(struct nv50_hw_query
*hq
, uint64_t res64
[8])
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;
114 debug_printf("invalid metric type: %d\n",
115 hq
->base
.type
- NV50_HW_METRIC_QUERY(0));
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
)
126 struct nv50_hw_metric_query
*hmq
= nv50_hw_metric_query(hq
);
127 union pipe_query_result results
[4] = {};
128 uint64_t res64
[4] = {};
132 for (i
= 0; i
< hmq
->num_queries
; i
++) {
133 ret
= hmq
->queries
[i
]->funcs
->get_query_result(nv50
, hmq
->queries
[i
],
137 res64
[i
] = *(uint64_t *)&results
[i
];
140 *(uint64_t *)result
= sm11_hw_metric_calc_result(hq
, res64
);
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
,
151 struct nv50_hw_query
*
152 nv50_hw_metric_create_query(struct nv50_context
*nv50
, unsigned type
)
154 const struct nv50_hw_metric_query_cfg
*cfg
;
155 struct nv50_hw_metric_query
*hmq
;
156 struct nv50_hw_query
*hq
;
159 if (type
< NV50_HW_METRIC_QUERY(0) || type
> NV50_HW_METRIC_QUERY_LAST
)
162 hmq
= CALLOC_STRUCT(nv50_hw_metric_query
);
167 hq
->funcs
= &hw_metric_query_funcs
;
168 hq
->base
.type
= type
;
170 cfg
= nv50_hw_metric_query_get_cfg(nv50
, hq
);
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
);
185 nv50_hw_metric_get_driver_query_info(struct nv50_screen
*screen
, unsigned id
,
186 struct pipe_driver_query_info
*info
)
191 if (screen
->base
.class_3d
>= NV84_3D_CLASS
)
192 count
+= NV50_HW_METRIC_QUERY_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
;