1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2021 Google, Inc. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * SPDX-License-Identifier: MIT 5bf215546Sopenharmony_ci */ 6bf215546Sopenharmony_ci 7bf215546Sopenharmony_ci#include "fd_pps_driver.h" 8bf215546Sopenharmony_ci 9bf215546Sopenharmony_ci#include <cstring> 10bf215546Sopenharmony_ci#include <iostream> 11bf215546Sopenharmony_ci#include <perfetto.h> 12bf215546Sopenharmony_ci 13bf215546Sopenharmony_ci#include "pps/pps.h" 14bf215546Sopenharmony_ci#include "pps/pps_algorithm.h" 15bf215546Sopenharmony_ci 16bf215546Sopenharmony_cinamespace pps 17bf215546Sopenharmony_ci{ 18bf215546Sopenharmony_ci 19bf215546Sopenharmony_cidouble 20bf215546Sopenharmony_cisafe_div(uint64_t a, uint64_t b) 21bf215546Sopenharmony_ci{ 22bf215546Sopenharmony_ci if (b == 0) 23bf215546Sopenharmony_ci return 0; 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci return a / static_cast<double>(b); 26bf215546Sopenharmony_ci} 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_cifloat 29bf215546Sopenharmony_cipercent(uint64_t a, uint64_t b) 30bf215546Sopenharmony_ci{ 31bf215546Sopenharmony_ci /* Sometimes we get bogus values but we want for the timeline 32bf215546Sopenharmony_ci * to look nice without higher than 100% values. 33bf215546Sopenharmony_ci */ 34bf215546Sopenharmony_ci if (b == 0 || a > b) 35bf215546Sopenharmony_ci return 0; 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci return 100.f * (a / static_cast<double>(b)); 38bf215546Sopenharmony_ci} 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ciuint64_t 41bf215546Sopenharmony_ciFreedrenoDriver::get_min_sampling_period_ns() 42bf215546Sopenharmony_ci{ 43bf215546Sopenharmony_ci return 100000; 44bf215546Sopenharmony_ci} 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci/* 47bf215546Sopenharmony_ciTODO this sees like it would be largely the same for a5xx as well 48bf215546Sopenharmony_ci(ie. same countable names).. 49bf215546Sopenharmony_ci */ 50bf215546Sopenharmony_civoid 51bf215546Sopenharmony_ciFreedrenoDriver::setup_a6xx_counters() 52bf215546Sopenharmony_ci{ 53bf215546Sopenharmony_ci /* TODO is there a reason to want more than one group? */ 54bf215546Sopenharmony_ci CounterGroup group = {}; 55bf215546Sopenharmony_ci group.name = "counters"; 56bf215546Sopenharmony_ci groups.clear(); 57bf215546Sopenharmony_ci counters.clear(); 58bf215546Sopenharmony_ci countables.clear(); 59bf215546Sopenharmony_ci enabled_counters.clear(); 60bf215546Sopenharmony_ci groups.emplace_back(std::move(group)); 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci /* 63bf215546Sopenharmony_ci * Create the countables that we'll be using. 64bf215546Sopenharmony_ci */ 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci auto PERF_CP_ALWAYS_COUNT = countable("PERF_CP_ALWAYS_COUNT"); 67bf215546Sopenharmony_ci auto PERF_CP_BUSY_CYCLES = countable("PERF_CP_BUSY_CYCLES"); 68bf215546Sopenharmony_ci auto PERF_RB_3D_PIXELS = countable("PERF_RB_3D_PIXELS"); 69bf215546Sopenharmony_ci auto PERF_TP_L1_CACHELINE_MISSES = countable("PERF_TP_L1_CACHELINE_MISSES"); 70bf215546Sopenharmony_ci auto PERF_TP_L1_CACHELINE_REQUESTS = countable("PERF_TP_L1_CACHELINE_REQUESTS"); 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_ci auto PERF_TP_OUTPUT_PIXELS = countable("PERF_TP_OUTPUT_PIXELS"); 73bf215546Sopenharmony_ci auto PERF_TP_OUTPUT_PIXELS_ANISO = countable("PERF_TP_OUTPUT_PIXELS_ANISO"); 74bf215546Sopenharmony_ci auto PERF_TP_OUTPUT_PIXELS_BILINEAR = countable("PERF_TP_OUTPUT_PIXELS_BILINEAR"); 75bf215546Sopenharmony_ci auto PERF_TP_OUTPUT_PIXELS_POINT = countable("PERF_TP_OUTPUT_PIXELS_POINT"); 76bf215546Sopenharmony_ci auto PERF_TP_OUTPUT_PIXELS_ZERO_LOD = countable("PERF_TP_OUTPUT_PIXELS_ZERO_LOD"); 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci auto PERF_TSE_INPUT_PRIM = countable("PERF_TSE_INPUT_PRIM"); 79bf215546Sopenharmony_ci auto PERF_TSE_CLIPPED_PRIM = countable("PERF_TSE_CLIPPED_PRIM"); 80bf215546Sopenharmony_ci auto PERF_TSE_TRIVAL_REJ_PRIM = countable("PERF_TSE_TRIVAL_REJ_PRIM"); 81bf215546Sopenharmony_ci auto PERF_TSE_OUTPUT_VISIBLE_PRIM = countable("PERF_TSE_OUTPUT_VISIBLE_PRIM"); 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci auto PERF_SP_BUSY_CYCLES = countable("PERF_SP_BUSY_CYCLES"); 84bf215546Sopenharmony_ci auto PERF_SP_ALU_WORKING_CYCLES = countable("PERF_SP_ALU_WORKING_CYCLES"); 85bf215546Sopenharmony_ci auto PERF_SP_EFU_WORKING_CYCLES = countable("PERF_SP_EFU_WORKING_CYCLES"); 86bf215546Sopenharmony_ci auto PERF_SP_VS_STAGE_EFU_INSTRUCTIONS = countable("PERF_SP_VS_STAGE_EFU_INSTRUCTIONS"); 87bf215546Sopenharmony_ci auto PERF_SP_VS_STAGE_FULL_ALU_INSTRUCTIONS = countable("PERF_SP_VS_STAGE_FULL_ALU_INSTRUCTIONS"); 88bf215546Sopenharmony_ci auto PERF_SP_VS_STAGE_TEX_INSTRUCTIONS = countable("PERF_SP_VS_STAGE_TEX_INSTRUCTIONS"); 89bf215546Sopenharmony_ci auto PERF_SP_FS_STAGE_EFU_INSTRUCTIONS = countable("PERF_SP_FS_STAGE_EFU_INSTRUCTIONS"); 90bf215546Sopenharmony_ci auto PERF_SP_FS_STAGE_FULL_ALU_INSTRUCTIONS = countable("PERF_SP_FS_STAGE_FULL_ALU_INSTRUCTIONS"); 91bf215546Sopenharmony_ci auto PERF_SP_FS_STAGE_HALF_ALU_INSTRUCTIONS = countable("PERF_SP_FS_STAGE_HALF_ALU_INSTRUCTIONS"); 92bf215546Sopenharmony_ci auto PERF_SP_STALL_CYCLES_TP = countable("PERF_SP_STALL_CYCLES_TP"); 93bf215546Sopenharmony_ci auto PERF_SP_ANY_EU_WORKING_FS_STAGE = countable("PERF_SP_ANY_EU_WORKING_FS_STAGE"); 94bf215546Sopenharmony_ci auto PERF_SP_ANY_EU_WORKING_VS_STAGE = countable("PERF_SP_ANY_EU_WORKING_VS_STAGE"); 95bf215546Sopenharmony_ci auto PERF_SP_ANY_EU_WORKING_CS_STAGE = countable("PERF_SP_ANY_EU_WORKING_CS_STAGE"); 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci auto PERF_UCHE_STALL_CYCLES_ARBITER = countable("PERF_UCHE_STALL_CYCLES_ARBITER"); 98bf215546Sopenharmony_ci auto PERF_UCHE_VBIF_READ_BEATS_TP = countable("PERF_UCHE_VBIF_READ_BEATS_TP"); 99bf215546Sopenharmony_ci auto PERF_UCHE_VBIF_READ_BEATS_VFD = countable("PERF_UCHE_VBIF_READ_BEATS_VFD"); 100bf215546Sopenharmony_ci auto PERF_UCHE_VBIF_READ_BEATS_SP = countable("PERF_UCHE_VBIF_READ_BEATS_SP"); 101bf215546Sopenharmony_ci auto PERF_UCHE_READ_REQUESTS_TP = countable("PERF_UCHE_READ_REQUESTS_TP"); 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci auto PERF_PC_STALL_CYCLES_VFD = countable("PERF_PC_STALL_CYCLES_VFD"); 104bf215546Sopenharmony_ci auto PERF_PC_VS_INVOCATIONS = countable("PERF_PC_VS_INVOCATIONS"); 105bf215546Sopenharmony_ci auto PERF_PC_VERTEX_HITS = countable("PERF_PC_VERTEX_HITS"); 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_ci auto PERF_HLSQ_QUADS = countable("PERF_HLSQ_QUADS"); /* Quads (fragments / 4) produced */ 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci auto PERF_CP_NUM_PREEMPTIONS = countable("PERF_CP_NUM_PREEMPTIONS"); 110bf215546Sopenharmony_ci auto PERF_CP_PREEMPTION_REACTION_DELAY = countable("PERF_CP_PREEMPTION_REACTION_DELAY"); 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci /* TODO: resolve() tells there is no PERF_CMPDECMP_VBIF_READ_DATA */ 113bf215546Sopenharmony_ci // auto PERF_CMPDECMP_VBIF_READ_DATA = countable("PERF_CMPDECMP_VBIF_READ_DATA"); 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci /* 116bf215546Sopenharmony_ci * And then setup the derived counters that we are exporting to 117bf215546Sopenharmony_ci * pps based on the captured countable values. 118bf215546Sopenharmony_ci * 119bf215546Sopenharmony_ci * We try to expose the same counters as blob: 120bf215546Sopenharmony_ci * https://gpuinspector.dev/docs/gpu-counters/qualcomm 121bf215546Sopenharmony_ci */ 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci counter("GPU Frequency", Counter::Units::Hertz, [=]() { 124bf215546Sopenharmony_ci return PERF_CP_ALWAYS_COUNT / time; 125bf215546Sopenharmony_ci } 126bf215546Sopenharmony_ci ); 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci counter("GPU % Utilization", Counter::Units::Percent, [=]() { 129bf215546Sopenharmony_ci return percent(PERF_CP_BUSY_CYCLES / time, max_freq); 130bf215546Sopenharmony_ci } 131bf215546Sopenharmony_ci ); 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci counter("TP L1 Cache Misses", Counter::Units::None, [=]() { 134bf215546Sopenharmony_ci return PERF_TP_L1_CACHELINE_MISSES / time; 135bf215546Sopenharmony_ci } 136bf215546Sopenharmony_ci ); 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci counter("Shader Core Utilization", Counter::Units::Percent, [=]() { 139bf215546Sopenharmony_ci return percent(PERF_SP_BUSY_CYCLES / time, max_freq * info->num_sp_cores); 140bf215546Sopenharmony_ci } 141bf215546Sopenharmony_ci ); 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ci /* TODO: verify */ 144bf215546Sopenharmony_ci counter("(?) % Texture Fetch Stall", Counter::Units::Percent, [=]() { 145bf215546Sopenharmony_ci return percent(PERF_SP_STALL_CYCLES_TP / time, max_freq * info->num_sp_cores); 146bf215546Sopenharmony_ci } 147bf215546Sopenharmony_ci ); 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_ci /* TODO: verify */ 150bf215546Sopenharmony_ci counter("(?) % Vertex Fetch Stall", Counter::Units::Percent, [=]() { 151bf215546Sopenharmony_ci return percent(PERF_PC_STALL_CYCLES_VFD / time, max_freq * info->num_sp_cores); 152bf215546Sopenharmony_ci } 153bf215546Sopenharmony_ci ); 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_ci counter("L1 Texture Cache Miss Per Pixel", Counter::Units::None, [=]() { 156bf215546Sopenharmony_ci return safe_div(PERF_TP_L1_CACHELINE_MISSES, PERF_HLSQ_QUADS * 4); 157bf215546Sopenharmony_ci } 158bf215546Sopenharmony_ci ); 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci counter("% Texture L1 Miss", Counter::Units::Percent, [=]() { 161bf215546Sopenharmony_ci return percent(PERF_TP_L1_CACHELINE_MISSES, PERF_TP_L1_CACHELINE_REQUESTS); 162bf215546Sopenharmony_ci } 163bf215546Sopenharmony_ci ); 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci counter("% Texture L2 Miss", Counter::Units::Percent, [=]() { 166bf215546Sopenharmony_ci return percent(PERF_UCHE_VBIF_READ_BEATS_TP / 2, PERF_UCHE_READ_REQUESTS_TP); 167bf215546Sopenharmony_ci } 168bf215546Sopenharmony_ci ); 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci /* TODO: verify */ 171bf215546Sopenharmony_ci counter("(?) % Stalled on System Memory", Counter::Units::Percent, [=]() { 172bf215546Sopenharmony_ci return percent(PERF_UCHE_STALL_CYCLES_ARBITER / time, max_freq * info->num_sp_cores); 173bf215546Sopenharmony_ci } 174bf215546Sopenharmony_ci ); 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci counter("Pre-clipped Polygons / Second", Counter::Units::None, [=]() { 177bf215546Sopenharmony_ci return PERF_TSE_INPUT_PRIM * (1.f / time); 178bf215546Sopenharmony_ci } 179bf215546Sopenharmony_ci ); 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci counter("% Prims Trivially Rejected", Counter::Units::Percent, [=]() { 182bf215546Sopenharmony_ci return percent(PERF_TSE_TRIVAL_REJ_PRIM, PERF_TSE_INPUT_PRIM); 183bf215546Sopenharmony_ci } 184bf215546Sopenharmony_ci ); 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci counter("% Prims Clipped", Counter::Units::Percent, [=]() { 187bf215546Sopenharmony_ci return percent(PERF_TSE_CLIPPED_PRIM, PERF_TSE_INPUT_PRIM); 188bf215546Sopenharmony_ci } 189bf215546Sopenharmony_ci ); 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_ci counter("Average Vertices / Polygon", Counter::Units::None, [=]() { 192bf215546Sopenharmony_ci return PERF_PC_VS_INVOCATIONS / PERF_TSE_INPUT_PRIM; 193bf215546Sopenharmony_ci } 194bf215546Sopenharmony_ci ); 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci counter("Reused Vertices / Second", Counter::Units::None, [=]() { 197bf215546Sopenharmony_ci return PERF_PC_VERTEX_HITS * (1.f / time); 198bf215546Sopenharmony_ci } 199bf215546Sopenharmony_ci ); 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci counter("Average Polygon Area", Counter::Units::None, [=]() { 202bf215546Sopenharmony_ci return safe_div(PERF_HLSQ_QUADS * 4, PERF_TSE_OUTPUT_VISIBLE_PRIM); 203bf215546Sopenharmony_ci } 204bf215546Sopenharmony_ci ); 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci /* TODO: find formula */ 207bf215546Sopenharmony_ci // counter("% Shaders Busy", Counter::Units::Percent, [=]() { 208bf215546Sopenharmony_ci // return 100.0 * 0; 209bf215546Sopenharmony_ci // } 210bf215546Sopenharmony_ci // ); 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci counter("Vertices Shaded / Second", Counter::Units::None, [=]() { 213bf215546Sopenharmony_ci return PERF_PC_VS_INVOCATIONS * (1.f / time); 214bf215546Sopenharmony_ci } 215bf215546Sopenharmony_ci ); 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ci counter("Fragments Shaded / Second", Counter::Units::None, [=]() { 218bf215546Sopenharmony_ci return PERF_HLSQ_QUADS * 4 * (1.f / time); 219bf215546Sopenharmony_ci } 220bf215546Sopenharmony_ci ); 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci counter("Vertex Instructions / Second", Counter::Units::None, [=]() { 223bf215546Sopenharmony_ci return (PERF_SP_VS_STAGE_FULL_ALU_INSTRUCTIONS + 224bf215546Sopenharmony_ci PERF_SP_VS_STAGE_EFU_INSTRUCTIONS) * (1.f / time); 225bf215546Sopenharmony_ci } 226bf215546Sopenharmony_ci ); 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci counter("Fragment Instructions / Second", Counter::Units::None, [=]() { 229bf215546Sopenharmony_ci return (PERF_SP_FS_STAGE_FULL_ALU_INSTRUCTIONS + 230bf215546Sopenharmony_ci PERF_SP_FS_STAGE_HALF_ALU_INSTRUCTIONS / 2 + 231bf215546Sopenharmony_ci PERF_SP_FS_STAGE_EFU_INSTRUCTIONS) * (1.f / time); 232bf215546Sopenharmony_ci } 233bf215546Sopenharmony_ci ); 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ci counter("Fragment ALU Instructions / Sec (Full)", Counter::Units::None, [=]() { 236bf215546Sopenharmony_ci return PERF_SP_FS_STAGE_FULL_ALU_INSTRUCTIONS * (1.f / time); 237bf215546Sopenharmony_ci } 238bf215546Sopenharmony_ci ); 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci counter("Fragment ALU Instructions / Sec (Half)", Counter::Units::None, [=]() { 241bf215546Sopenharmony_ci return PERF_SP_FS_STAGE_HALF_ALU_INSTRUCTIONS * (1.f / time); 242bf215546Sopenharmony_ci } 243bf215546Sopenharmony_ci ); 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci counter("Fragment EFU Instructions / Second", Counter::Units::None, [=]() { 246bf215546Sopenharmony_ci return PERF_SP_FS_STAGE_EFU_INSTRUCTIONS * (1.f / time); 247bf215546Sopenharmony_ci } 248bf215546Sopenharmony_ci ); 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci counter("Textures / Vertex", Counter::Units::None, [=]() { 251bf215546Sopenharmony_ci return safe_div(PERF_SP_VS_STAGE_TEX_INSTRUCTIONS, PERF_PC_VS_INVOCATIONS); 252bf215546Sopenharmony_ci } 253bf215546Sopenharmony_ci ); 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci counter("Textures / Fragment", Counter::Units::None, [=]() { 256bf215546Sopenharmony_ci return safe_div(PERF_TP_OUTPUT_PIXELS, PERF_HLSQ_QUADS * 4); 257bf215546Sopenharmony_ci } 258bf215546Sopenharmony_ci ); 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ci counter("ALU / Vertex", Counter::Units::None, [=]() { 261bf215546Sopenharmony_ci return safe_div(PERF_SP_VS_STAGE_FULL_ALU_INSTRUCTIONS, PERF_PC_VS_INVOCATIONS); 262bf215546Sopenharmony_ci } 263bf215546Sopenharmony_ci ); 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_ci counter("EFU / Vertex", Counter::Units::None, [=]() { 266bf215546Sopenharmony_ci return safe_div(PERF_SP_VS_STAGE_EFU_INSTRUCTIONS, PERF_PC_VS_INVOCATIONS); 267bf215546Sopenharmony_ci } 268bf215546Sopenharmony_ci ); 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci counter("ALU / Fragment", Counter::Units::None, [=]() { 271bf215546Sopenharmony_ci return safe_div(PERF_SP_FS_STAGE_FULL_ALU_INSTRUCTIONS + 272bf215546Sopenharmony_ci PERF_SP_FS_STAGE_HALF_ALU_INSTRUCTIONS / 2, PERF_HLSQ_QUADS); 273bf215546Sopenharmony_ci } 274bf215546Sopenharmony_ci ); 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ci counter("EFU / Fragment", Counter::Units::None, [=]() { 277bf215546Sopenharmony_ci return safe_div(PERF_SP_FS_STAGE_EFU_INSTRUCTIONS, PERF_HLSQ_QUADS); 278bf215546Sopenharmony_ci } 279bf215546Sopenharmony_ci ); 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci counter("% Time Shading Vertices", Counter::Units::Percent, [=]() { 282bf215546Sopenharmony_ci return percent(PERF_SP_ANY_EU_WORKING_VS_STAGE, 283bf215546Sopenharmony_ci (PERF_SP_ANY_EU_WORKING_VS_STAGE + 284bf215546Sopenharmony_ci PERF_SP_ANY_EU_WORKING_FS_STAGE + 285bf215546Sopenharmony_ci PERF_SP_ANY_EU_WORKING_CS_STAGE)); 286bf215546Sopenharmony_ci } 287bf215546Sopenharmony_ci ); 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci counter("% Time Shading Fragments", Counter::Units::Percent, [=]() { 290bf215546Sopenharmony_ci return percent(PERF_SP_ANY_EU_WORKING_FS_STAGE, 291bf215546Sopenharmony_ci (PERF_SP_ANY_EU_WORKING_VS_STAGE + 292bf215546Sopenharmony_ci PERF_SP_ANY_EU_WORKING_FS_STAGE + 293bf215546Sopenharmony_ci PERF_SP_ANY_EU_WORKING_CS_STAGE)); 294bf215546Sopenharmony_ci } 295bf215546Sopenharmony_ci ); 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci counter("% Time Compute", Counter::Units::Percent, [=]() { 298bf215546Sopenharmony_ci return percent(PERF_SP_ANY_EU_WORKING_CS_STAGE, 299bf215546Sopenharmony_ci (PERF_SP_ANY_EU_WORKING_VS_STAGE + 300bf215546Sopenharmony_ci PERF_SP_ANY_EU_WORKING_FS_STAGE + 301bf215546Sopenharmony_ci PERF_SP_ANY_EU_WORKING_CS_STAGE)); 302bf215546Sopenharmony_ci } 303bf215546Sopenharmony_ci ); 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci counter("% Shader ALU Capacity Utilized", Counter::Units::Percent, [=]() { 306bf215546Sopenharmony_ci return percent((PERF_SP_VS_STAGE_FULL_ALU_INSTRUCTIONS + 307bf215546Sopenharmony_ci PERF_SP_FS_STAGE_FULL_ALU_INSTRUCTIONS + 308bf215546Sopenharmony_ci PERF_SP_FS_STAGE_HALF_ALU_INSTRUCTIONS / 2) / 64, 309bf215546Sopenharmony_ci PERF_SP_BUSY_CYCLES); 310bf215546Sopenharmony_ci } 311bf215546Sopenharmony_ci ); 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_ci counter("% Time ALUs Working", Counter::Units::Percent, [=]() { 314bf215546Sopenharmony_ci return percent(PERF_SP_ALU_WORKING_CYCLES / 2, PERF_SP_BUSY_CYCLES); 315bf215546Sopenharmony_ci } 316bf215546Sopenharmony_ci ); 317bf215546Sopenharmony_ci 318bf215546Sopenharmony_ci counter("% Time EFUs Working", Counter::Units::Percent, [=]() { 319bf215546Sopenharmony_ci return percent(PERF_SP_EFU_WORKING_CYCLES / 2, PERF_SP_BUSY_CYCLES); 320bf215546Sopenharmony_ci } 321bf215546Sopenharmony_ci ); 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_ci counter("% Anisotropic Filtered", Counter::Units::Percent, [=]() { 324bf215546Sopenharmony_ci return percent(PERF_TP_OUTPUT_PIXELS_ANISO, PERF_TP_OUTPUT_PIXELS); 325bf215546Sopenharmony_ci } 326bf215546Sopenharmony_ci ); 327bf215546Sopenharmony_ci 328bf215546Sopenharmony_ci counter("% Linear Filtered", Counter::Units::Percent, [=]() { 329bf215546Sopenharmony_ci return percent(PERF_TP_OUTPUT_PIXELS_BILINEAR, PERF_TP_OUTPUT_PIXELS); 330bf215546Sopenharmony_ci } 331bf215546Sopenharmony_ci ); 332bf215546Sopenharmony_ci 333bf215546Sopenharmony_ci counter("% Nearest Filtered", Counter::Units::Percent, [=]() { 334bf215546Sopenharmony_ci return percent(PERF_TP_OUTPUT_PIXELS_POINT, PERF_TP_OUTPUT_PIXELS); 335bf215546Sopenharmony_ci } 336bf215546Sopenharmony_ci ); 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci counter("% Non-Base Level Textures", Counter::Units::Percent, [=]() { 339bf215546Sopenharmony_ci return percent(PERF_TP_OUTPUT_PIXELS_ZERO_LOD, PERF_TP_OUTPUT_PIXELS); 340bf215546Sopenharmony_ci } 341bf215546Sopenharmony_ci ); 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci /* Reads from KGSL_PERFCOUNTER_GROUP_VBIF countable=63 */ 344bf215546Sopenharmony_ci // counter("Read Total (Bytes/sec)", Counter::Units::Byte, [=]() { 345bf215546Sopenharmony_ci // return * (1.f / time); 346bf215546Sopenharmony_ci // } 347bf215546Sopenharmony_ci // ); 348bf215546Sopenharmony_ci 349bf215546Sopenharmony_ci /* Reads from KGSL_PERFCOUNTER_GROUP_VBIF countable=84 */ 350bf215546Sopenharmony_ci // counter("Write Total (Bytes/sec)", Counter::Units::Byte, [=]() { 351bf215546Sopenharmony_ci // return * (1.f / time); 352bf215546Sopenharmony_ci // } 353bf215546Sopenharmony_ci // ); 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_ci /* Cannot get PERF_CMPDECMP_VBIF_READ_DATA countable */ 356bf215546Sopenharmony_ci // counter("Texture Memory Read BW (Bytes/Second)", Counter::Units::Byte, [=]() { 357bf215546Sopenharmony_ci // return (PERF_CMPDECMP_VBIF_READ_DATA + PERF_UCHE_VBIF_READ_BEATS_TP) * (1.f / time); 358bf215546Sopenharmony_ci // } 359bf215546Sopenharmony_ci // ); 360bf215546Sopenharmony_ci 361bf215546Sopenharmony_ci /* TODO: verify */ 362bf215546Sopenharmony_ci counter("(?) Vertex Memory Read (Bytes/Second)", Counter::Units::Byte, [=]() { 363bf215546Sopenharmony_ci return PERF_UCHE_VBIF_READ_BEATS_VFD * 32 * (1.f / time); 364bf215546Sopenharmony_ci } 365bf215546Sopenharmony_ci ); 366bf215546Sopenharmony_ci 367bf215546Sopenharmony_ci /* TODO: verify */ 368bf215546Sopenharmony_ci counter("SP Memory Read (Bytes/Second)", Counter::Units::Byte, [=]() { 369bf215546Sopenharmony_ci return PERF_UCHE_VBIF_READ_BEATS_SP * 32 * (1.f / time); 370bf215546Sopenharmony_ci } 371bf215546Sopenharmony_ci ); 372bf215546Sopenharmony_ci 373bf215546Sopenharmony_ci counter("Avg Bytes / Fragment", Counter::Units::Byte, [=]() { 374bf215546Sopenharmony_ci return safe_div(PERF_UCHE_VBIF_READ_BEATS_TP * 32, PERF_HLSQ_QUADS * 4); 375bf215546Sopenharmony_ci } 376bf215546Sopenharmony_ci ); 377bf215546Sopenharmony_ci 378bf215546Sopenharmony_ci counter("Avg Bytes / Vertex", Counter::Units::Byte, [=]() { 379bf215546Sopenharmony_ci return safe_div(PERF_UCHE_VBIF_READ_BEATS_VFD * 32, PERF_PC_VS_INVOCATIONS); 380bf215546Sopenharmony_ci } 381bf215546Sopenharmony_ci ); 382bf215546Sopenharmony_ci 383bf215546Sopenharmony_ci counter("Preemptions / second", Counter::Units::None, [=]() { 384bf215546Sopenharmony_ci return PERF_CP_NUM_PREEMPTIONS * (1.f / time); 385bf215546Sopenharmony_ci } 386bf215546Sopenharmony_ci ); 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_ci counter("Avg Preemption Delay", Counter::Units::None, [=]() { 389bf215546Sopenharmony_ci return PERF_CP_PREEMPTION_REACTION_DELAY * (1.f / time); 390bf215546Sopenharmony_ci } 391bf215546Sopenharmony_ci ); 392bf215546Sopenharmony_ci} 393bf215546Sopenharmony_ci 394bf215546Sopenharmony_ci/** 395bf215546Sopenharmony_ci * Generate an submit the cmdstream to configure the counter/countable 396bf215546Sopenharmony_ci * muxing 397bf215546Sopenharmony_ci */ 398bf215546Sopenharmony_civoid 399bf215546Sopenharmony_ciFreedrenoDriver::configure_counters(bool reset, bool wait) 400bf215546Sopenharmony_ci{ 401bf215546Sopenharmony_ci struct fd_submit *submit = fd_submit_new(pipe); 402bf215546Sopenharmony_ci enum fd_ringbuffer_flags flags = 403bf215546Sopenharmony_ci (enum fd_ringbuffer_flags)(FD_RINGBUFFER_PRIMARY | FD_RINGBUFFER_GROWABLE); 404bf215546Sopenharmony_ci struct fd_ringbuffer *ring = fd_submit_new_ringbuffer(submit, 0x1000, flags); 405bf215546Sopenharmony_ci 406bf215546Sopenharmony_ci for (auto countable : countables) 407bf215546Sopenharmony_ci countable.configure(ring, reset); 408bf215546Sopenharmony_ci 409bf215546Sopenharmony_ci struct fd_submit_fence fence = {}; 410bf215546Sopenharmony_ci util_queue_fence_init(&fence.ready); 411bf215546Sopenharmony_ci 412bf215546Sopenharmony_ci fd_submit_flush(submit, -1, &fence); 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_ci util_queue_fence_wait(&fence.ready); 415bf215546Sopenharmony_ci 416bf215546Sopenharmony_ci fd_ringbuffer_del(ring); 417bf215546Sopenharmony_ci fd_submit_del(submit); 418bf215546Sopenharmony_ci 419bf215546Sopenharmony_ci if (wait) 420bf215546Sopenharmony_ci fd_pipe_wait(pipe, &fence.fence); 421bf215546Sopenharmony_ci} 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci/** 424bf215546Sopenharmony_ci * Read the current counter values and record the time. 425bf215546Sopenharmony_ci */ 426bf215546Sopenharmony_civoid 427bf215546Sopenharmony_ciFreedrenoDriver::collect_countables() 428bf215546Sopenharmony_ci{ 429bf215546Sopenharmony_ci last_dump_ts = perfetto::base::GetBootTimeNs().count(); 430bf215546Sopenharmony_ci 431bf215546Sopenharmony_ci for (auto countable : countables) 432bf215546Sopenharmony_ci countable.collect(); 433bf215546Sopenharmony_ci} 434bf215546Sopenharmony_ci 435bf215546Sopenharmony_cibool 436bf215546Sopenharmony_ciFreedrenoDriver::init_perfcnt() 437bf215546Sopenharmony_ci{ 438bf215546Sopenharmony_ci uint64_t val; 439bf215546Sopenharmony_ci 440bf215546Sopenharmony_ci dev = fd_device_new(drm_device.fd); 441bf215546Sopenharmony_ci pipe = fd_pipe_new(dev, FD_PIPE_3D); 442bf215546Sopenharmony_ci dev_id = fd_pipe_dev_id(pipe); 443bf215546Sopenharmony_ci 444bf215546Sopenharmony_ci if (fd_pipe_get_param(pipe, FD_MAX_FREQ, &val)) { 445bf215546Sopenharmony_ci PERFETTO_FATAL("Could not get MAX_FREQ"); 446bf215546Sopenharmony_ci return false; 447bf215546Sopenharmony_ci } 448bf215546Sopenharmony_ci max_freq = val; 449bf215546Sopenharmony_ci 450bf215546Sopenharmony_ci if (fd_pipe_get_param(pipe, FD_SUSPEND_COUNT, &val)) { 451bf215546Sopenharmony_ci PERFETTO_ILOG("Could not get SUSPEND_COUNT"); 452bf215546Sopenharmony_ci } else { 453bf215546Sopenharmony_ci suspend_count = val; 454bf215546Sopenharmony_ci has_suspend_count = true; 455bf215546Sopenharmony_ci } 456bf215546Sopenharmony_ci 457bf215546Sopenharmony_ci fd_pipe_set_param(pipe, FD_SYSPROF, 1); 458bf215546Sopenharmony_ci 459bf215546Sopenharmony_ci perfcntrs = fd_perfcntrs(fd_pipe_dev_id(pipe), &num_perfcntrs); 460bf215546Sopenharmony_ci if (num_perfcntrs == 0) { 461bf215546Sopenharmony_ci PERFETTO_FATAL("No hw counters available"); 462bf215546Sopenharmony_ci return false; 463bf215546Sopenharmony_ci } 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci assigned_counters.resize(num_perfcntrs); 466bf215546Sopenharmony_ci assigned_counters.assign(assigned_counters.size(), 0); 467bf215546Sopenharmony_ci 468bf215546Sopenharmony_ci switch (fd_dev_gen(dev_id)) { 469bf215546Sopenharmony_ci case 6: 470bf215546Sopenharmony_ci setup_a6xx_counters(); 471bf215546Sopenharmony_ci break; 472bf215546Sopenharmony_ci default: 473bf215546Sopenharmony_ci PERFETTO_FATAL("Unsupported GPU: a%03u", fd_dev_gpu_id(dev_id)); 474bf215546Sopenharmony_ci return false; 475bf215546Sopenharmony_ci } 476bf215546Sopenharmony_ci 477bf215546Sopenharmony_ci state.resize(next_countable_id); 478bf215546Sopenharmony_ci 479bf215546Sopenharmony_ci for (auto countable : countables) 480bf215546Sopenharmony_ci countable.resolve(); 481bf215546Sopenharmony_ci 482bf215546Sopenharmony_ci info = fd_dev_info(dev_id); 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_ci io = fd_dt_find_io(); 485bf215546Sopenharmony_ci if (!io) { 486bf215546Sopenharmony_ci PERFETTO_FATAL("Could not map GPU I/O space"); 487bf215546Sopenharmony_ci return false; 488bf215546Sopenharmony_ci } 489bf215546Sopenharmony_ci 490bf215546Sopenharmony_ci configure_counters(true, true); 491bf215546Sopenharmony_ci collect_countables(); 492bf215546Sopenharmony_ci 493bf215546Sopenharmony_ci return true; 494bf215546Sopenharmony_ci} 495bf215546Sopenharmony_ci 496bf215546Sopenharmony_civoid 497bf215546Sopenharmony_ciFreedrenoDriver::enable_counter(const uint32_t counter_id) 498bf215546Sopenharmony_ci{ 499bf215546Sopenharmony_ci enabled_counters.push_back(counters[counter_id]); 500bf215546Sopenharmony_ci} 501bf215546Sopenharmony_ci 502bf215546Sopenharmony_civoid 503bf215546Sopenharmony_ciFreedrenoDriver::enable_all_counters() 504bf215546Sopenharmony_ci{ 505bf215546Sopenharmony_ci enabled_counters.reserve(counters.size()); 506bf215546Sopenharmony_ci for (auto &counter : counters) { 507bf215546Sopenharmony_ci enabled_counters.push_back(counter); 508bf215546Sopenharmony_ci } 509bf215546Sopenharmony_ci} 510bf215546Sopenharmony_ci 511bf215546Sopenharmony_civoid 512bf215546Sopenharmony_ciFreedrenoDriver::enable_perfcnt(const uint64_t /* sampling_period_ns */) 513bf215546Sopenharmony_ci{ 514bf215546Sopenharmony_ci} 515bf215546Sopenharmony_ci 516bf215546Sopenharmony_cibool 517bf215546Sopenharmony_ciFreedrenoDriver::dump_perfcnt() 518bf215546Sopenharmony_ci{ 519bf215546Sopenharmony_ci if (has_suspend_count) { 520bf215546Sopenharmony_ci uint64_t val; 521bf215546Sopenharmony_ci 522bf215546Sopenharmony_ci fd_pipe_get_param(pipe, FD_SUSPEND_COUNT, &val); 523bf215546Sopenharmony_ci 524bf215546Sopenharmony_ci if (suspend_count != val) { 525bf215546Sopenharmony_ci PERFETTO_ILOG("Device had suspended!"); 526bf215546Sopenharmony_ci 527bf215546Sopenharmony_ci suspend_count = val; 528bf215546Sopenharmony_ci 529bf215546Sopenharmony_ci configure_counters(true, true); 530bf215546Sopenharmony_ci collect_countables(); 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci /* We aren't going to have anything sensible by comparing 533bf215546Sopenharmony_ci * current values to values from prior to the suspend, so 534bf215546Sopenharmony_ci * just skip this sampling period. 535bf215546Sopenharmony_ci */ 536bf215546Sopenharmony_ci return false; 537bf215546Sopenharmony_ci } 538bf215546Sopenharmony_ci } 539bf215546Sopenharmony_ci 540bf215546Sopenharmony_ci auto last_ts = last_dump_ts; 541bf215546Sopenharmony_ci 542bf215546Sopenharmony_ci /* Capture the timestamp from the *start* of the sampling period: */ 543bf215546Sopenharmony_ci last_capture_ts = last_dump_ts; 544bf215546Sopenharmony_ci 545bf215546Sopenharmony_ci collect_countables(); 546bf215546Sopenharmony_ci 547bf215546Sopenharmony_ci auto elapsed_time_ns = last_dump_ts - last_ts; 548bf215546Sopenharmony_ci 549bf215546Sopenharmony_ci time = (float)elapsed_time_ns / 1000000000.0; 550bf215546Sopenharmony_ci 551bf215546Sopenharmony_ci /* On older kernels that dont' support querying the suspend- 552bf215546Sopenharmony_ci * count, just send configuration cmdstream regularly to keep 553bf215546Sopenharmony_ci * the GPU alive and correctly configured for the countables 554bf215546Sopenharmony_ci * we want 555bf215546Sopenharmony_ci */ 556bf215546Sopenharmony_ci if (!has_suspend_count) { 557bf215546Sopenharmony_ci configure_counters(false, false); 558bf215546Sopenharmony_ci } 559bf215546Sopenharmony_ci 560bf215546Sopenharmony_ci return true; 561bf215546Sopenharmony_ci} 562bf215546Sopenharmony_ci 563bf215546Sopenharmony_ciuint64_t FreedrenoDriver::next() 564bf215546Sopenharmony_ci{ 565bf215546Sopenharmony_ci auto ret = last_capture_ts; 566bf215546Sopenharmony_ci last_capture_ts = 0; 567bf215546Sopenharmony_ci return ret; 568bf215546Sopenharmony_ci} 569bf215546Sopenharmony_ci 570bf215546Sopenharmony_civoid FreedrenoDriver::disable_perfcnt() 571bf215546Sopenharmony_ci{ 572bf215546Sopenharmony_ci /* There isn't really any disable, only reconfiguring which countables 573bf215546Sopenharmony_ci * get muxed to which counters 574bf215546Sopenharmony_ci */ 575bf215546Sopenharmony_ci} 576bf215546Sopenharmony_ci 577bf215546Sopenharmony_ci/* 578bf215546Sopenharmony_ci * Countable 579bf215546Sopenharmony_ci */ 580bf215546Sopenharmony_ci 581bf215546Sopenharmony_ciFreedrenoDriver::Countable 582bf215546Sopenharmony_ciFreedrenoDriver::countable(std::string name) 583bf215546Sopenharmony_ci{ 584bf215546Sopenharmony_ci auto countable = Countable(this, name); 585bf215546Sopenharmony_ci countables.emplace_back(countable); 586bf215546Sopenharmony_ci return countable; 587bf215546Sopenharmony_ci} 588bf215546Sopenharmony_ci 589bf215546Sopenharmony_ciFreedrenoDriver::Countable::Countable(FreedrenoDriver *d, std::string name) 590bf215546Sopenharmony_ci : id {d->next_countable_id++}, d {d}, name {name} 591bf215546Sopenharmony_ci{ 592bf215546Sopenharmony_ci} 593bf215546Sopenharmony_ci 594bf215546Sopenharmony_ci/* Emit register writes on ring to configure counter/countable muxing: */ 595bf215546Sopenharmony_civoid 596bf215546Sopenharmony_ciFreedrenoDriver::Countable::configure(struct fd_ringbuffer *ring, bool reset) 597bf215546Sopenharmony_ci{ 598bf215546Sopenharmony_ci const struct fd_perfcntr_countable *countable = d->state[id].countable; 599bf215546Sopenharmony_ci const struct fd_perfcntr_counter *counter = d->state[id].counter; 600bf215546Sopenharmony_ci 601bf215546Sopenharmony_ci OUT_PKT7(ring, CP_WAIT_FOR_IDLE, 0); 602bf215546Sopenharmony_ci 603bf215546Sopenharmony_ci if (counter->enable && reset) { 604bf215546Sopenharmony_ci OUT_PKT4(ring, counter->enable, 1); 605bf215546Sopenharmony_ci OUT_RING(ring, 0); 606bf215546Sopenharmony_ci } 607bf215546Sopenharmony_ci 608bf215546Sopenharmony_ci if (counter->clear && reset) { 609bf215546Sopenharmony_ci OUT_PKT4(ring, counter->clear, 1); 610bf215546Sopenharmony_ci OUT_RING(ring, 1); 611bf215546Sopenharmony_ci 612bf215546Sopenharmony_ci OUT_PKT4(ring, counter->clear, 1); 613bf215546Sopenharmony_ci OUT_RING(ring, 0); 614bf215546Sopenharmony_ci } 615bf215546Sopenharmony_ci 616bf215546Sopenharmony_ci OUT_PKT4(ring, counter->select_reg, 1); 617bf215546Sopenharmony_ci OUT_RING(ring, countable->selector); 618bf215546Sopenharmony_ci 619bf215546Sopenharmony_ci if (counter->enable && reset) { 620bf215546Sopenharmony_ci OUT_PKT4(ring, counter->enable, 1); 621bf215546Sopenharmony_ci OUT_RING(ring, 1); 622bf215546Sopenharmony_ci } 623bf215546Sopenharmony_ci} 624bf215546Sopenharmony_ci 625bf215546Sopenharmony_ci/* Collect current counter value and calculate delta since last sample: */ 626bf215546Sopenharmony_civoid 627bf215546Sopenharmony_ciFreedrenoDriver::Countable::collect() 628bf215546Sopenharmony_ci{ 629bf215546Sopenharmony_ci const struct fd_perfcntr_counter *counter = d->state[id].counter; 630bf215546Sopenharmony_ci 631bf215546Sopenharmony_ci d->state[id].last_value = d->state[id].value; 632bf215546Sopenharmony_ci 633bf215546Sopenharmony_ci uint32_t *reg_lo = (uint32_t *)d->io + counter->counter_reg_lo; 634bf215546Sopenharmony_ci uint32_t *reg_hi = (uint32_t *)d->io + counter->counter_reg_hi; 635bf215546Sopenharmony_ci 636bf215546Sopenharmony_ci uint32_t lo = *reg_lo; 637bf215546Sopenharmony_ci uint32_t hi = *reg_hi; 638bf215546Sopenharmony_ci 639bf215546Sopenharmony_ci d->state[id].value = lo | ((uint64_t)hi << 32); 640bf215546Sopenharmony_ci} 641bf215546Sopenharmony_ci 642bf215546Sopenharmony_ci/* Resolve the countable and assign next counter from it's group: */ 643bf215546Sopenharmony_civoid 644bf215546Sopenharmony_ciFreedrenoDriver::Countable::resolve() 645bf215546Sopenharmony_ci{ 646bf215546Sopenharmony_ci for (unsigned i = 0; i < d->num_perfcntrs; i++) { 647bf215546Sopenharmony_ci const struct fd_perfcntr_group *g = &d->perfcntrs[i]; 648bf215546Sopenharmony_ci for (unsigned j = 0; j < g->num_countables; j++) { 649bf215546Sopenharmony_ci const struct fd_perfcntr_countable *c = &g->countables[j]; 650bf215546Sopenharmony_ci if (name == c->name) { 651bf215546Sopenharmony_ci d->state[id].countable = c; 652bf215546Sopenharmony_ci 653bf215546Sopenharmony_ci /* Assign a counter from the same group: */ 654bf215546Sopenharmony_ci assert(d->assigned_counters[i] < g->num_counters); 655bf215546Sopenharmony_ci d->state[id].counter = &g->counters[d->assigned_counters[i]++]; 656bf215546Sopenharmony_ci 657bf215546Sopenharmony_ci std::cout << "Countable: " << name << ", group=" << g->name << 658bf215546Sopenharmony_ci ", counter=" << d->assigned_counters[i] - 1 << "\n"; 659bf215546Sopenharmony_ci 660bf215546Sopenharmony_ci return; 661bf215546Sopenharmony_ci } 662bf215546Sopenharmony_ci } 663bf215546Sopenharmony_ci } 664bf215546Sopenharmony_ci unreachable("no such countable!"); 665bf215546Sopenharmony_ci} 666bf215546Sopenharmony_ci 667bf215546Sopenharmony_ciuint64_t 668bf215546Sopenharmony_ciFreedrenoDriver::Countable::get_value() const 669bf215546Sopenharmony_ci{ 670bf215546Sopenharmony_ci return d->state[id].value - d->state[id].last_value; 671bf215546Sopenharmony_ci} 672bf215546Sopenharmony_ci 673bf215546Sopenharmony_ci/* 674bf215546Sopenharmony_ci * DerivedCounter 675bf215546Sopenharmony_ci */ 676bf215546Sopenharmony_ci 677bf215546Sopenharmony_ciFreedrenoDriver::DerivedCounter::DerivedCounter(FreedrenoDriver *d, std::string name, 678bf215546Sopenharmony_ci Counter::Units units, 679bf215546Sopenharmony_ci std::function<int64_t()> derive) 680bf215546Sopenharmony_ci : Counter(d->next_counter_id++, name, 0) 681bf215546Sopenharmony_ci{ 682bf215546Sopenharmony_ci std::cout << "DerivedCounter: " << name << ", id=" << id << "\n"; 683bf215546Sopenharmony_ci this->units = units; 684bf215546Sopenharmony_ci set_getter([=](const Counter &c, const Driver &d) { 685bf215546Sopenharmony_ci return derive(); 686bf215546Sopenharmony_ci } 687bf215546Sopenharmony_ci ); 688bf215546Sopenharmony_ci} 689bf215546Sopenharmony_ci 690bf215546Sopenharmony_ciFreedrenoDriver::DerivedCounter 691bf215546Sopenharmony_ciFreedrenoDriver::counter(std::string name, Counter::Units units, 692bf215546Sopenharmony_ci std::function<int64_t()> derive) 693bf215546Sopenharmony_ci{ 694bf215546Sopenharmony_ci auto counter = DerivedCounter(this, name, units, derive); 695bf215546Sopenharmony_ci counters.emplace_back(counter); 696bf215546Sopenharmony_ci return counter; 697bf215546Sopenharmony_ci} 698bf215546Sopenharmony_ci 699bf215546Sopenharmony_ciuint32_t 700bf215546Sopenharmony_ciFreedrenoDriver::gpu_clock_id() const 701bf215546Sopenharmony_ci{ 702bf215546Sopenharmony_ci return perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME; 703bf215546Sopenharmony_ci} 704bf215546Sopenharmony_ci 705bf215546Sopenharmony_ciuint64_t 706bf215546Sopenharmony_ciFreedrenoDriver::gpu_timestamp() const 707bf215546Sopenharmony_ci{ 708bf215546Sopenharmony_ci return perfetto::base::GetBootTimeNs().count(); 709bf215546Sopenharmony_ci} 710bf215546Sopenharmony_ci 711bf215546Sopenharmony_ci} // namespace pps 712