Path: blob/21.2-virgl/src/gallium/drivers/nouveau/nv50/nv50_query_hw_metric.c
4574 views
/*1* Copyright 2015 Samuel Pitoiset2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice shall be included in11* all copies or substantial portions of the Software.12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR17* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,18* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR19* OTHER DEALINGS IN THE SOFTWARE.20*/2122#include "nv50/nv50_context.h"23#include "nv50/nv50_query_hw_metric.h"24#include "nv50/nv50_query_hw_sm.h"2526/* === PERFORMANCE MONITORING METRICS for NV84+ === */27static const char *nv50_hw_metric_names[] =28{29"metric-branch_efficiency",30};3132struct nv50_hw_metric_query_cfg {33uint32_t queries[4];34uint32_t num_queries;35};3637#define _SM(n) NV50_HW_SM_QUERY(NV50_HW_SM_QUERY_ ##n)38#define _M(n, c) [NV50_HW_METRIC_QUERY_##n] = c3940/* ==== Compute capability 1.1 (G84+) ==== */41static const struct nv50_hw_metric_query_cfg42sm11_branch_efficiency =43{44.queries[0] = _SM(BRANCH),45.queries[1] = _SM(DIVERGENT_BRANCH),46.num_queries = 2,47};4849static const struct nv50_hw_metric_query_cfg *sm11_hw_metric_queries[] =50{51_M(BRANCH_EFFICIENCY, &sm11_branch_efficiency),52};5354#undef _SM55#undef _M5657static const struct nv50_hw_metric_query_cfg *58nv50_hw_metric_query_get_cfg(struct nv50_context *nv50,59struct nv50_hw_query *hq)60{61struct nv50_query *q = &hq->base;62return sm11_hw_metric_queries[q->type - NV50_HW_METRIC_QUERY(0)];63}6465static void66nv50_hw_metric_destroy_query(struct nv50_context *nv50,67struct nv50_hw_query *hq)68{69struct nv50_hw_metric_query *hmq = nv50_hw_metric_query(hq);70unsigned i;7172for (i = 0; i < hmq->num_queries; i++)73if (hmq->queries[i]->funcs->destroy_query)74hmq->queries[i]->funcs->destroy_query(nv50, hmq->queries[i]);75FREE(hmq);76}7778static bool79nv50_hw_metric_begin_query(struct nv50_context *nv50, struct nv50_hw_query *hq)80{81struct nv50_hw_metric_query *hmq = nv50_hw_metric_query(hq);82bool ret = false;83unsigned i;8485for (i = 0; i < hmq->num_queries; i++) {86ret = hmq->queries[i]->funcs->begin_query(nv50, hmq->queries[i]);87if (!ret)88return ret;89}90return ret;91}9293static void94nv50_hw_metric_end_query(struct nv50_context *nv50, struct nv50_hw_query *hq)95{96struct nv50_hw_metric_query *hmq = nv50_hw_metric_query(hq);97unsigned i;9899for (i = 0; i < hmq->num_queries; i++)100hmq->queries[i]->funcs->end_query(nv50, hmq->queries[i]);101}102103static uint64_t104sm11_hw_metric_calc_result(struct nv50_hw_query *hq, uint64_t res64[4])105{106switch (hq->base.type - NV50_HW_METRIC_QUERY(0)) {107case NV50_HW_METRIC_QUERY_BRANCH_EFFICIENCY:108/* (branch / (branch + divergent_branch)) * 100 */109if (res64[0] + res64[1])110return (res64[0] / (double)(res64[0] + res64[1])) * 100;111break;112default:113debug_printf("invalid metric type: %d\n",114hq->base.type - NV50_HW_METRIC_QUERY(0));115break;116}117return 0;118}119120static bool121nv50_hw_metric_get_query_result(struct nv50_context *nv50,122struct nv50_hw_query *hq, bool wait,123union pipe_query_result *result)124{125struct nv50_hw_metric_query *hmq = nv50_hw_metric_query(hq);126union pipe_query_result results[4] = {};127uint64_t res64[4] = {};128bool ret = false;129unsigned i;130131for (i = 0; i < hmq->num_queries; i++) {132ret = hmq->queries[i]->funcs->get_query_result(nv50, hmq->queries[i],133wait, &results[i]);134if (!ret)135return ret;136res64[i] = *(uint64_t *)&results[i];137}138139*(uint64_t *)result = sm11_hw_metric_calc_result(hq, res64);140return ret;141}142143static 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};149150struct nv50_hw_query *151nv50_hw_metric_create_query(struct nv50_context *nv50, unsigned type)152{153const struct nv50_hw_metric_query_cfg *cfg;154struct nv50_hw_metric_query *hmq;155struct nv50_hw_query *hq;156unsigned i;157158if (type < NV50_HW_METRIC_QUERY(0) || type > NV50_HW_METRIC_QUERY_LAST)159return NULL;160161hmq = CALLOC_STRUCT(nv50_hw_metric_query);162if (!hmq)163return NULL;164165hq = &hmq->base;166hq->funcs = &hw_metric_query_funcs;167hq->base.type = type;168169cfg = nv50_hw_metric_query_get_cfg(nv50, hq);170171for (i = 0; i < cfg->num_queries; i++) {172hmq->queries[i] = nv50_hw_sm_create_query(nv50, cfg->queries[i]);173if (!hmq->queries[i]) {174nv50_hw_metric_destroy_query(nv50, hq);175return NULL;176}177hmq->num_queries++;178}179180return hq;181}182183int184nv50_hw_metric_get_driver_query_info(struct nv50_screen *screen, unsigned id,185struct pipe_driver_query_info *info)186{187int count = 0;188189if (screen->compute)190if (screen->base.class_3d >= NV84_3D_CLASS)191count += NV50_HW_METRIC_QUERY_COUNT;192193if (!info)194return count;195196if (id < count) {197if (screen->compute) {198if (screen->base.class_3d >= NV84_3D_CLASS) {199info->name = nv50_hw_metric_names[id];200info->query_type = NV50_HW_METRIC_QUERY(id);201info->group_id = NV50_HW_METRIC_QUERY_GROUP;202return 1;203}204}205}206return 0;207}208209210