1/* 2 * Copyright 2020 Advanced Micro Devices, Inc. 3 * Copyright © 2020 Valve Corporation 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 * IN THE SOFTWARE. 23 */ 24#include "ac_rgp.h" 25 26#include "util/macros.h" 27#include "util/os_misc.h" 28#include "util/os_time.h" 29#include "util/u_process.h" 30#include "util/u_math.h" 31 32#include "ac_spm.h" 33#include "ac_sqtt.h" 34#include "ac_gpu_info.h" 35#ifdef _WIN32 36#define AMDGPU_VRAM_TYPE_UNKNOWN 0 37#define AMDGPU_VRAM_TYPE_GDDR1 1 38#define AMDGPU_VRAM_TYPE_DDR2 2 39#define AMDGPU_VRAM_TYPE_GDDR3 3 40#define AMDGPU_VRAM_TYPE_GDDR4 4 41#define AMDGPU_VRAM_TYPE_GDDR5 5 42#define AMDGPU_VRAM_TYPE_HBM 6 43#define AMDGPU_VRAM_TYPE_DDR3 7 44#define AMDGPU_VRAM_TYPE_DDR4 8 45#define AMDGPU_VRAM_TYPE_GDDR6 9 46#define AMDGPU_VRAM_TYPE_DDR5 10 47#else 48#include "drm-uapi/amdgpu_drm.h" 49#endif 50 51#include <stdbool.h> 52#include <string.h> 53 54#define SQTT_FILE_MAGIC_NUMBER 0x50303042 55#define SQTT_FILE_VERSION_MAJOR 1 56#define SQTT_FILE_VERSION_MINOR 5 57 58#define SQTT_GPU_NAME_MAX_SIZE 256 59#define SQTT_MAX_NUM_SE 32 60#define SQTT_SA_PER_SE 2 61 62enum sqtt_version 63{ 64 SQTT_VERSION_NONE = 0x0, 65 SQTT_VERSION_2_2 = 0x5, /* GFX8 */ 66 SQTT_VERSION_2_3 = 0x6, /* GFX9 */ 67 SQTT_VERSION_2_4 = 0x7 /* GFX10+ */ 68}; 69 70/** 71 * SQTT chunks. 72 */ 73enum sqtt_file_chunk_type 74{ 75 SQTT_FILE_CHUNK_TYPE_ASIC_INFO, 76 SQTT_FILE_CHUNK_TYPE_SQTT_DESC, 77 SQTT_FILE_CHUNK_TYPE_SQTT_DATA, 78 SQTT_FILE_CHUNK_TYPE_API_INFO, 79 SQTT_FILE_CHUNK_TYPE_RESERVED, 80 SQTT_FILE_CHUNK_TYPE_QUEUE_EVENT_TIMINGS, 81 SQTT_FILE_CHUNK_TYPE_CLOCK_CALIBRATION, 82 SQTT_FILE_CHUNK_TYPE_CPU_INFO, 83 SQTT_FILE_CHUNK_TYPE_SPM_DB, 84 SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_DATABASE, 85 SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_LOADER_EVENTS, 86 SQTT_FILE_CHUNK_TYPE_PSO_CORRELATION, 87 SQTT_FILE_CHUNK_TYPE_INSTRUMENTATION_TABLE, 88 SQTT_FILE_CHUNK_TYPE_COUNT 89}; 90 91struct sqtt_file_chunk_id { 92 enum sqtt_file_chunk_type type : 8; 93 int32_t index : 8; 94 int32_t reserved : 16; 95}; 96 97struct sqtt_file_chunk_header { 98 struct sqtt_file_chunk_id chunk_id; 99 uint16_t minor_version; 100 uint16_t major_version; 101 int32_t size_in_bytes; 102 int32_t padding; 103}; 104 105/** 106 * SQTT file header. 107 */ 108struct sqtt_file_header_flags { 109 union { 110 struct { 111 int32_t is_semaphore_queue_timing_etw : 1; 112 int32_t no_queue_semaphore_timestamps : 1; 113 int32_t reserved : 30; 114 }; 115 116 uint32_t value; 117 }; 118}; 119 120struct sqtt_file_header { 121 uint32_t magic_number; 122 uint32_t version_major; 123 uint32_t version_minor; 124 struct sqtt_file_header_flags flags; 125 int32_t chunk_offset; 126 int32_t second; 127 int32_t minute; 128 int32_t hour; 129 int32_t day_in_month; 130 int32_t month; 131 int32_t year; 132 int32_t day_in_week; 133 int32_t day_in_year; 134 int32_t is_daylight_savings; 135}; 136 137static_assert(sizeof(struct sqtt_file_header) == 56, "sqtt_file_header doesn't match RGP spec"); 138 139static void ac_sqtt_fill_header(struct sqtt_file_header *header) 140{ 141 struct tm *timep, result; 142 time_t raw_time; 143 144 header->magic_number = SQTT_FILE_MAGIC_NUMBER; 145 header->version_major = SQTT_FILE_VERSION_MAJOR; 146 header->version_minor = SQTT_FILE_VERSION_MINOR; 147 header->flags.value = 0; 148 header->flags.is_semaphore_queue_timing_etw = 1; 149 header->flags.no_queue_semaphore_timestamps = 0; 150 header->chunk_offset = sizeof(*header); 151 152 time(&raw_time); 153 timep = os_localtime(&raw_time, &result); 154 155 header->second = timep->tm_sec; 156 header->minute = timep->tm_min; 157 header->hour = timep->tm_hour; 158 header->day_in_month = timep->tm_mday; 159 header->month = timep->tm_mon; 160 header->year = timep->tm_year; 161 header->day_in_week = timep->tm_wday; 162 header->day_in_year = timep->tm_yday; 163 header->is_daylight_savings = timep->tm_isdst; 164} 165 166/** 167 * SQTT CPU info. 168 */ 169struct sqtt_file_chunk_cpu_info { 170 struct sqtt_file_chunk_header header; 171 uint32_t vendor_id[4]; 172 uint32_t processor_brand[12]; 173 uint32_t reserved[2]; 174 uint64_t cpu_timestamp_freq; 175 uint32_t clock_speed; 176 uint32_t num_logical_cores; 177 uint32_t num_physical_cores; 178 uint32_t system_ram_size; 179}; 180 181static_assert(sizeof(struct sqtt_file_chunk_cpu_info) == 112, 182 "sqtt_file_chunk_cpu_info doesn't match RGP spec"); 183 184static void ac_sqtt_fill_cpu_info(struct sqtt_file_chunk_cpu_info *chunk) 185{ 186 uint32_t cpu_clock_speed_total = 0; 187 uint64_t system_ram_size = 0; 188 char line[1024]; 189 FILE *f; 190 191 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_CPU_INFO; 192 chunk->header.chunk_id.index = 0; 193 chunk->header.major_version = 0; 194 chunk->header.minor_version = 0; 195 chunk->header.size_in_bytes = sizeof(*chunk); 196 197 chunk->cpu_timestamp_freq = 1000000000; /* tick set to 1ns */ 198 199 strncpy((char *)chunk->vendor_id, "Unknown", sizeof(chunk->vendor_id)); 200 strncpy((char *)chunk->processor_brand, "Unknown", sizeof(chunk->processor_brand)); 201 chunk->clock_speed = 0; 202 chunk->num_logical_cores = 0; 203 chunk->num_physical_cores = 0; 204 chunk->system_ram_size = 0; 205 if (os_get_total_physical_memory(&system_ram_size)) 206 chunk->system_ram_size = system_ram_size / (1024 * 1024); 207 208 /* Parse cpuinfo to get more detailled information. */ 209 f = fopen("/proc/cpuinfo", "r"); 210 if (!f) 211 return; 212 213 while (fgets(line, sizeof(line), f)) { 214 char *str; 215 216 /* Parse vendor name. */ 217 str = strstr(line, "vendor_id"); 218 if (str) { 219 char *ptr = (char *)chunk->vendor_id; 220 char *v = strtok(str, ":"); 221 v = strtok(NULL, ":"); 222 strncpy(ptr, v + 1, sizeof(chunk->vendor_id) - 1); 223 ptr[sizeof(chunk->vendor_id) - 1] = '\0'; 224 } 225 226 /* Parse processor name. */ 227 str = strstr(line, "model name"); 228 if (str) { 229 char *ptr = (char *)chunk->processor_brand; 230 char *v = strtok(str, ":"); 231 v = strtok(NULL, ":"); 232 strncpy(ptr, v + 1, sizeof(chunk->processor_brand) - 1); 233 ptr[sizeof(chunk->processor_brand) - 1] = '\0'; 234 } 235 236 /* Parse the current CPU clock speed for each cores. */ 237 str = strstr(line, "cpu MHz"); 238 if (str) { 239 uint32_t v = 0; 240 if (sscanf(str, "cpu MHz : %d", &v) == 1) 241 cpu_clock_speed_total += v; 242 } 243 244 /* Parse the number of logical cores. */ 245 str = strstr(line, "siblings"); 246 if (str) { 247 uint32_t v = 0; 248 if (sscanf(str, "siblings : %d", &v) == 1) 249 chunk->num_logical_cores = v; 250 } 251 252 /* Parse the number of physical cores. */ 253 str = strstr(line, "cpu cores"); 254 if (str) { 255 uint32_t v = 0; 256 if (sscanf(str, "cpu cores : %d", &v) == 1) 257 chunk->num_physical_cores = v; 258 } 259 } 260 261 if (chunk->num_logical_cores) 262 chunk->clock_speed = cpu_clock_speed_total / chunk->num_logical_cores; 263 264 fclose(f); 265} 266 267/** 268 * SQTT ASIC info. 269 */ 270enum sqtt_file_chunk_asic_info_flags 271{ 272 SQTT_FILE_CHUNK_ASIC_INFO_FLAG_SC_PACKER_NUMBERING = (1 << 0), 273 SQTT_FILE_CHUNK_ASIC_INFO_FLAG_PS1_EVENT_TOKENS_ENABLED = (1 << 1) 274}; 275 276enum sqtt_gpu_type 277{ 278 SQTT_GPU_TYPE_UNKNOWN = 0x0, 279 SQTT_GPU_TYPE_INTEGRATED = 0x1, 280 SQTT_GPU_TYPE_DISCRETE = 0x2, 281 SQTT_GPU_TYPE_VIRTUAL = 0x3 282}; 283 284enum sqtt_gfxip_level 285{ 286 SQTT_GFXIP_LEVEL_NONE = 0x0, 287 SQTT_GFXIP_LEVEL_GFXIP_6 = 0x1, 288 SQTT_GFXIP_LEVEL_GFXIP_7 = 0x2, 289 SQTT_GFXIP_LEVEL_GFXIP_8 = 0x3, 290 SQTT_GFXIP_LEVEL_GFXIP_8_1 = 0x4, 291 SQTT_GFXIP_LEVEL_GFXIP_9 = 0x5, 292 SQTT_GFXIP_LEVEL_GFXIP_10_1 = 0x7, 293 SQTT_GFXIP_LEVEL_GFXIP_10_3 = 0x9, 294}; 295 296enum sqtt_memory_type 297{ 298 SQTT_MEMORY_TYPE_UNKNOWN = 0x0, 299 SQTT_MEMORY_TYPE_DDR = 0x1, 300 SQTT_MEMORY_TYPE_DDR2 = 0x2, 301 SQTT_MEMORY_TYPE_DDR3 = 0x3, 302 SQTT_MEMORY_TYPE_DDR4 = 0x4, 303 SQTT_MEMORY_TYPE_GDDR3 = 0x10, 304 SQTT_MEMORY_TYPE_GDDR4 = 0x11, 305 SQTT_MEMORY_TYPE_GDDR5 = 0x12, 306 SQTT_MEMORY_TYPE_GDDR6 = 0x13, 307 SQTT_MEMORY_TYPE_HBM = 0x20, 308 SQTT_MEMORY_TYPE_HBM2 = 0x21, 309 SQTT_MEMORY_TYPE_HBM3 = 0x22, 310 SQTT_MEMORY_TYPE_LPDDR4 = 0x30, 311 SQTT_MEMORY_TYPE_LPDDR5 = 0x31, 312}; 313 314struct sqtt_file_chunk_asic_info { 315 struct sqtt_file_chunk_header header; 316 uint64_t flags; 317 uint64_t trace_shader_core_clock; 318 uint64_t trace_memory_clock; 319 int32_t device_id; 320 int32_t device_revision_id; 321 int32_t vgprs_per_simd; 322 int32_t sgprs_per_simd; 323 int32_t shader_engines; 324 int32_t compute_unit_per_shader_engine; 325 int32_t simd_per_compute_unit; 326 int32_t wavefronts_per_simd; 327 int32_t minimum_vgpr_alloc; 328 int32_t vgpr_alloc_granularity; 329 int32_t minimum_sgpr_alloc; 330 int32_t sgpr_alloc_granularity; 331 int32_t hardware_contexts; 332 enum sqtt_gpu_type gpu_type; 333 enum sqtt_gfxip_level gfxip_level; 334 int32_t gpu_index; 335 int32_t gds_size; 336 int32_t gds_per_shader_engine; 337 int32_t ce_ram_size; 338 int32_t ce_ram_size_graphics; 339 int32_t ce_ram_size_compute; 340 int32_t max_number_of_dedicated_cus; 341 int64_t vram_size; 342 int32_t vram_bus_width; 343 int32_t l2_cache_size; 344 int32_t l1_cache_size; 345 int32_t lds_size; 346 char gpu_name[SQTT_GPU_NAME_MAX_SIZE]; 347 float alu_per_clock; 348 float texture_per_clock; 349 float prims_per_clock; 350 float pixels_per_clock; 351 uint64_t gpu_timestamp_frequency; 352 uint64_t max_shader_core_clock; 353 uint64_t max_memory_clock; 354 uint32_t memory_ops_per_clock; 355 enum sqtt_memory_type memory_chip_type; 356 uint32_t lds_granularity; 357 uint16_t cu_mask[SQTT_MAX_NUM_SE][SQTT_SA_PER_SE]; 358 char reserved1[128]; 359 char padding[4]; 360}; 361 362static_assert(sizeof(struct sqtt_file_chunk_asic_info) == 720, 363 "sqtt_file_chunk_asic_info doesn't match RGP spec"); 364 365static enum sqtt_gfxip_level ac_gfx_level_to_sqtt_gfxip_level(enum amd_gfx_level gfx_level) 366{ 367 switch (gfx_level) { 368 case GFX8: 369 return SQTT_GFXIP_LEVEL_GFXIP_8; 370 case GFX9: 371 return SQTT_GFXIP_LEVEL_GFXIP_9; 372 case GFX10: 373 return SQTT_GFXIP_LEVEL_GFXIP_10_1; 374 case GFX10_3: 375 return SQTT_GFXIP_LEVEL_GFXIP_10_3; 376 default: 377 unreachable("Invalid gfx level"); 378 } 379} 380 381static enum sqtt_memory_type ac_vram_type_to_sqtt_memory_type(uint32_t vram_type) 382{ 383 switch (vram_type) { 384 case AMDGPU_VRAM_TYPE_UNKNOWN: 385 return SQTT_MEMORY_TYPE_UNKNOWN; 386 case AMDGPU_VRAM_TYPE_DDR2: 387 return SQTT_MEMORY_TYPE_DDR2; 388 case AMDGPU_VRAM_TYPE_DDR3: 389 return SQTT_MEMORY_TYPE_DDR3; 390 case AMDGPU_VRAM_TYPE_DDR4: 391 return SQTT_MEMORY_TYPE_DDR4; 392 case AMDGPU_VRAM_TYPE_GDDR5: 393 return SQTT_MEMORY_TYPE_GDDR5; 394 case AMDGPU_VRAM_TYPE_HBM: 395 return SQTT_MEMORY_TYPE_HBM; 396 case AMDGPU_VRAM_TYPE_GDDR6: 397 return SQTT_MEMORY_TYPE_GDDR6; 398 case AMDGPU_VRAM_TYPE_DDR5: 399 return SQTT_MEMORY_TYPE_LPDDR5; 400 case AMDGPU_VRAM_TYPE_GDDR1: 401 case AMDGPU_VRAM_TYPE_GDDR3: 402 case AMDGPU_VRAM_TYPE_GDDR4: 403 default: 404 unreachable("Invalid vram type"); 405 } 406} 407 408static uint32_t ac_memory_ops_per_clock(uint32_t vram_type) 409{ 410 switch (vram_type) { 411 case AMDGPU_VRAM_TYPE_UNKNOWN: 412 return 0; 413 case AMDGPU_VRAM_TYPE_DDR2: 414 case AMDGPU_VRAM_TYPE_DDR3: 415 case AMDGPU_VRAM_TYPE_DDR4: 416 case AMDGPU_VRAM_TYPE_HBM: 417 return 2; 418 case AMDGPU_VRAM_TYPE_DDR5: 419 case AMDGPU_VRAM_TYPE_GDDR5: 420 return 4; 421 case AMDGPU_VRAM_TYPE_GDDR6: 422 return 16; 423 case AMDGPU_VRAM_TYPE_GDDR1: 424 case AMDGPU_VRAM_TYPE_GDDR3: 425 case AMDGPU_VRAM_TYPE_GDDR4: 426 default: 427 unreachable("Invalid vram type"); 428 } 429} 430 431static void ac_sqtt_fill_asic_info(struct radeon_info *rad_info, 432 struct sqtt_file_chunk_asic_info *chunk) 433{ 434 bool has_wave32 = rad_info->gfx_level >= GFX10; 435 436 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_ASIC_INFO; 437 chunk->header.chunk_id.index = 0; 438 chunk->header.major_version = 0; 439 chunk->header.minor_version = 4; 440 chunk->header.size_in_bytes = sizeof(*chunk); 441 442 chunk->flags = 0; 443 444 /* All chips older than GFX9 are affected by the "SPI not 445 * differentiating pkr_id for newwave commands" bug. 446 */ 447 if (rad_info->gfx_level < GFX9) 448 chunk->flags |= SQTT_FILE_CHUNK_ASIC_INFO_FLAG_SC_PACKER_NUMBERING; 449 450 /* Only GFX9+ support PS1 events. */ 451 if (rad_info->gfx_level >= GFX9) 452 chunk->flags |= SQTT_FILE_CHUNK_ASIC_INFO_FLAG_PS1_EVENT_TOKENS_ENABLED; 453 454 chunk->trace_shader_core_clock = rad_info->max_gpu_freq_mhz * 1000000ull; 455 chunk->trace_memory_clock = rad_info->memory_freq_mhz * 1000000ull; 456 457 /* RGP gets very confused if these clocks are 0. The numbers here are for profile_peak on 458 * VGH since that is the chips where we've seen the need for this workaround. */ 459 if (!chunk->trace_shader_core_clock) 460 chunk->trace_shader_core_clock = 1300000000; 461 if (!chunk->trace_memory_clock) 462 chunk->trace_memory_clock = 687000000; 463 464 chunk->device_id = rad_info->pci_id; 465 chunk->device_revision_id = rad_info->pci_rev_id; 466 chunk->vgprs_per_simd = rad_info->num_physical_wave64_vgprs_per_simd * (has_wave32 ? 2 : 1); 467 chunk->sgprs_per_simd = rad_info->num_physical_sgprs_per_simd; 468 chunk->shader_engines = rad_info->max_se; 469 chunk->compute_unit_per_shader_engine = rad_info->min_good_cu_per_sa * rad_info->max_sa_per_se; 470 chunk->simd_per_compute_unit = rad_info->num_simd_per_compute_unit; 471 chunk->wavefronts_per_simd = rad_info->max_wave64_per_simd; 472 473 chunk->minimum_vgpr_alloc = rad_info->min_wave64_vgpr_alloc; 474 chunk->vgpr_alloc_granularity = rad_info->wave64_vgpr_alloc_granularity * (has_wave32 ? 2 : 1); 475 chunk->minimum_sgpr_alloc = rad_info->min_sgpr_alloc; 476 chunk->sgpr_alloc_granularity = rad_info->sgpr_alloc_granularity; 477 478 chunk->hardware_contexts = 8; 479 chunk->gpu_type = 480 rad_info->has_dedicated_vram ? SQTT_GPU_TYPE_DISCRETE : SQTT_GPU_TYPE_INTEGRATED; 481 chunk->gfxip_level = ac_gfx_level_to_sqtt_gfxip_level(rad_info->gfx_level); 482 chunk->gpu_index = 0; 483 484 chunk->max_number_of_dedicated_cus = 0; 485 chunk->ce_ram_size = 0; 486 chunk->ce_ram_size_graphics = 0; 487 chunk->ce_ram_size_compute = 0; 488 489 chunk->vram_bus_width = rad_info->memory_bus_width; 490 chunk->vram_size = (uint64_t)rad_info->vram_size_kb * 1024; 491 chunk->l2_cache_size = rad_info->l2_cache_size; 492 chunk->l1_cache_size = rad_info->l1_cache_size; 493 chunk->lds_size = rad_info->lds_size_per_workgroup; 494 if (rad_info->gfx_level >= GFX10) { 495 /* RGP expects the LDS size in CU mode. */ 496 chunk->lds_size /= 2; 497 } 498 499 strncpy(chunk->gpu_name, rad_info->name, SQTT_GPU_NAME_MAX_SIZE - 1); 500 501 chunk->alu_per_clock = 0.0; 502 chunk->texture_per_clock = 0.0; 503 chunk->prims_per_clock = rad_info->max_se; 504 if (rad_info->gfx_level == GFX10) 505 chunk->prims_per_clock *= 2; 506 chunk->pixels_per_clock = 0.0; 507 508 chunk->gpu_timestamp_frequency = rad_info->clock_crystal_freq * 1000; 509 chunk->max_shader_core_clock = rad_info->max_gpu_freq_mhz * 1000000; 510 chunk->max_memory_clock = rad_info->memory_freq_mhz * 1000000; 511 chunk->memory_ops_per_clock = ac_memory_ops_per_clock(rad_info->vram_type); 512 chunk->memory_chip_type = ac_vram_type_to_sqtt_memory_type(rad_info->vram_type); 513 chunk->lds_granularity = rad_info->lds_encode_granularity; 514 515 for (unsigned se = 0; se < AMD_MAX_SE; se++) { 516 for (unsigned sa = 0; sa < AMD_MAX_SA_PER_SE; sa++) { 517 chunk->cu_mask[se][sa] = rad_info->cu_mask[se][sa]; 518 } 519 } 520} 521 522/** 523 * SQTT API info. 524 */ 525enum sqtt_api_type 526{ 527 SQTT_API_TYPE_DIRECTX_12, 528 SQTT_API_TYPE_VULKAN, 529 SQTT_API_TYPE_GENERIC, 530 SQTT_API_TYPE_OPENCL 531}; 532 533enum sqtt_instruction_trace_mode 534{ 535 SQTT_INSTRUCTION_TRACE_DISABLED = 0x0, 536 SQTT_INSTRUCTION_TRACE_FULL_FRAME = 0x1, 537 SQTT_INSTRUCTION_TRACE_API_PSO = 0x2, 538}; 539 540enum sqtt_profiling_mode 541{ 542 SQTT_PROFILING_MODE_PRESENT = 0x0, 543 SQTT_PROFILING_MODE_USER_MARKERS = 0x1, 544 SQTT_PROFILING_MODE_INDEX = 0x2, 545 SQTT_PROFILING_MODE_TAG = 0x3, 546}; 547 548union sqtt_profiling_mode_data { 549 struct { 550 char start[256]; 551 char end[256]; 552 } user_marker_profiling_data; 553 554 struct { 555 uint32_t start; 556 uint32_t end; 557 } index_profiling_data; 558 559 struct { 560 uint32_t begin_hi; 561 uint32_t begin_lo; 562 uint32_t end_hi; 563 uint32_t end_lo; 564 } tag_profiling_data; 565}; 566 567union sqtt_instruction_trace_data { 568 struct { 569 uint64_t api_pso_filter; 570 } api_pso_data; 571 572 struct { 573 char start[256]; 574 char end[256]; 575 } user_marker_data; 576}; 577 578struct sqtt_file_chunk_api_info { 579 struct sqtt_file_chunk_header header; 580 enum sqtt_api_type api_type; 581 uint16_t major_version; 582 uint16_t minor_version; 583 enum sqtt_profiling_mode profiling_mode; 584 uint32_t reserved; 585 union sqtt_profiling_mode_data profiling_mode_data; 586 enum sqtt_instruction_trace_mode instruction_trace_mode; 587 uint32_t reserved2; 588 union sqtt_instruction_trace_data instruction_trace_data; 589}; 590 591static_assert(sizeof(struct sqtt_file_chunk_api_info) == 1064, 592 "sqtt_file_chunk_api_info doesn't match RGP spec"); 593 594static void ac_sqtt_fill_api_info(struct sqtt_file_chunk_api_info *chunk) 595{ 596 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_API_INFO; 597 chunk->header.chunk_id.index = 0; 598 chunk->header.major_version = 0; 599 chunk->header.minor_version = 1; 600 chunk->header.size_in_bytes = sizeof(*chunk); 601 602 chunk->api_type = SQTT_API_TYPE_VULKAN; 603 chunk->major_version = 0; 604 chunk->minor_version = 0; 605 chunk->profiling_mode = SQTT_PROFILING_MODE_PRESENT; 606 chunk->instruction_trace_mode = SQTT_INSTRUCTION_TRACE_DISABLED; 607} 608 609struct sqtt_code_object_database_record { 610 uint32_t size; 611}; 612 613struct sqtt_file_chunk_code_object_database { 614 struct sqtt_file_chunk_header header; 615 uint32_t offset; 616 uint32_t flags; 617 uint32_t size; 618 uint32_t record_count; 619}; 620 621static void 622ac_sqtt_fill_code_object(struct rgp_code_object *rgp_code_object, 623 struct sqtt_file_chunk_code_object_database *chunk, 624 size_t file_offset, uint32_t chunk_size) 625{ 626 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_DATABASE; 627 chunk->header.chunk_id.index = 0; 628 chunk->header.major_version = 0; 629 chunk->header.minor_version = 0; 630 chunk->header.size_in_bytes = chunk_size; 631 chunk->offset = file_offset; 632 chunk->flags = 0; 633 chunk->size = chunk_size; 634 chunk->record_count = rgp_code_object->record_count; 635} 636 637struct sqtt_code_object_loader_events_record { 638 uint32_t loader_event_type; 639 uint32_t reserved; 640 uint64_t base_address; 641 uint64_t code_object_hash[2]; 642 uint64_t time_stamp; 643}; 644 645struct sqtt_file_chunk_code_object_loader_events { 646 struct sqtt_file_chunk_header header; 647 uint32_t offset; 648 uint32_t flags; 649 uint32_t record_size; 650 uint32_t record_count; 651}; 652 653static void 654ac_sqtt_fill_loader_events(struct rgp_loader_events *rgp_loader_events, 655 struct sqtt_file_chunk_code_object_loader_events *chunk, 656 size_t file_offset) 657{ 658 chunk->header.chunk_id.type = 659 SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_LOADER_EVENTS; 660 chunk->header.chunk_id.index = 0; 661 chunk->header.major_version = 1; 662 chunk->header.minor_version = 0; 663 chunk->header.size_in_bytes = (rgp_loader_events->record_count * 664 sizeof(struct sqtt_code_object_loader_events_record)) + 665 sizeof(*chunk); 666 chunk->offset = file_offset; 667 chunk->flags = 0; 668 chunk->record_size = sizeof(struct sqtt_code_object_loader_events_record); 669 chunk->record_count = rgp_loader_events->record_count; 670} 671struct sqtt_pso_correlation_record { 672 uint64_t api_pso_hash; 673 uint64_t pipeline_hash[2]; 674 char api_level_obj_name[64]; 675}; 676 677struct sqtt_file_chunk_pso_correlation { 678 struct sqtt_file_chunk_header header; 679 uint32_t offset; 680 uint32_t flags; 681 uint32_t record_size; 682 uint32_t record_count; 683}; 684 685static void 686ac_sqtt_fill_pso_correlation(struct rgp_pso_correlation *rgp_pso_correlation, 687 struct sqtt_file_chunk_pso_correlation *chunk, 688 size_t file_offset) 689{ 690 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_PSO_CORRELATION; 691 chunk->header.chunk_id.index = 0; 692 chunk->header.major_version = 0; 693 chunk->header.minor_version = 0; 694 chunk->header.size_in_bytes = (rgp_pso_correlation->record_count * 695 sizeof(struct sqtt_pso_correlation_record)) + 696 sizeof(*chunk); 697 chunk->offset = file_offset; 698 chunk->flags = 0; 699 chunk->record_size = sizeof(struct sqtt_pso_correlation_record); 700 chunk->record_count = rgp_pso_correlation->record_count; 701} 702 703/** 704 * SQTT desc info. 705 */ 706struct sqtt_file_chunk_sqtt_desc { 707 struct sqtt_file_chunk_header header; 708 int32_t shader_engine_index; 709 enum sqtt_version sqtt_version; 710 union { 711 struct { 712 int32_t instrumentation_version; 713 } v0; 714 struct { 715 int16_t instrumentation_spec_version; 716 int16_t instrumentation_api_version; 717 int32_t compute_unit_index; 718 } v1; 719 }; 720}; 721 722static_assert(sizeof(struct sqtt_file_chunk_sqtt_desc) == 32, 723 "sqtt_file_chunk_sqtt_desc doesn't match RGP spec"); 724 725static enum sqtt_version ac_gfx_level_to_sqtt_version(enum amd_gfx_level gfx_level) 726{ 727 switch (gfx_level) { 728 case GFX8: 729 return SQTT_VERSION_2_2; 730 case GFX9: 731 return SQTT_VERSION_2_3; 732 case GFX10: 733 return SQTT_VERSION_2_4; 734 case GFX10_3: 735 return SQTT_VERSION_2_4; 736 default: 737 unreachable("Invalid gfx level"); 738 } 739} 740 741static void ac_sqtt_fill_sqtt_desc(struct radeon_info *info, 742 struct sqtt_file_chunk_sqtt_desc *chunk, int32_t chunk_index, 743 int32_t shader_engine_index, int32_t compute_unit_index) 744{ 745 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_SQTT_DESC; 746 chunk->header.chunk_id.index = chunk_index; 747 chunk->header.major_version = 0; 748 chunk->header.minor_version = 2; 749 chunk->header.size_in_bytes = sizeof(*chunk); 750 751 chunk->sqtt_version = 752 ac_gfx_level_to_sqtt_version(info->gfx_level); 753 chunk->shader_engine_index = shader_engine_index; 754 chunk->v1.instrumentation_spec_version = 1; 755 chunk->v1.instrumentation_api_version = 0; 756 chunk->v1.compute_unit_index = compute_unit_index; 757} 758 759/** 760 * SQTT data info. 761 */ 762struct sqtt_file_chunk_sqtt_data { 763 struct sqtt_file_chunk_header header; 764 int32_t offset; /* in bytes */ 765 int32_t size; /* in bytes */ 766}; 767 768static_assert(sizeof(struct sqtt_file_chunk_sqtt_data) == 24, 769 "sqtt_file_chunk_sqtt_data doesn't match RGP spec"); 770 771static void ac_sqtt_fill_sqtt_data(struct sqtt_file_chunk_sqtt_data *chunk, int32_t chunk_index, 772 int32_t offset, int32_t size) 773{ 774 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_SQTT_DATA; 775 chunk->header.chunk_id.index = chunk_index; 776 chunk->header.major_version = 0; 777 chunk->header.minor_version = 0; 778 chunk->header.size_in_bytes = sizeof(*chunk) + size; 779 780 chunk->offset = sizeof(*chunk) + offset; 781 chunk->size = size; 782} 783 784/** 785 * SQTT queue event timings info. 786 */ 787struct sqtt_file_chunk_queue_event_timings { 788 struct sqtt_file_chunk_header header; 789 uint32_t queue_info_table_record_count; 790 uint32_t queue_info_table_size; 791 uint32_t queue_event_table_record_count; 792 uint32_t queue_event_table_size; 793}; 794 795static_assert(sizeof(struct sqtt_file_chunk_queue_event_timings) == 32, 796 "sqtt_file_chunk_queue_event_timings doesn't match RGP spec"); 797 798struct sqtt_queue_info_record { 799 uint64_t queue_id; 800 uint64_t queue_context; 801 struct sqtt_queue_hardware_info hardware_info; 802 uint32_t reserved; 803}; 804 805static_assert(sizeof(struct sqtt_queue_info_record) == 24, 806 "sqtt_queue_info_record doesn't match RGP spec"); 807 808struct sqtt_queue_event_record { 809 enum sqtt_queue_event_type event_type; 810 uint32_t sqtt_cb_id; 811 uint64_t frame_index; 812 uint32_t queue_info_index; 813 uint32_t submit_sub_index; 814 uint64_t api_id; 815 uint64_t cpu_timestamp; 816 uint64_t gpu_timestamps[2]; 817}; 818 819static_assert(sizeof(struct sqtt_queue_event_record) == 56, 820 "sqtt_queue_event_record doesn't match RGP spec"); 821 822static void 823ac_sqtt_fill_queue_event_timings(struct rgp_queue_info *rgp_queue_info, 824 struct rgp_queue_event *rgp_queue_event, 825 struct sqtt_file_chunk_queue_event_timings *chunk) 826{ 827 unsigned queue_info_size = 828 rgp_queue_info->record_count * sizeof(struct sqtt_queue_info_record); 829 unsigned queue_event_size = 830 rgp_queue_event->record_count * sizeof(struct sqtt_queue_event_record); 831 832 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_QUEUE_EVENT_TIMINGS; 833 chunk->header.chunk_id.index = 0; 834 chunk->header.major_version = 1; 835 chunk->header.minor_version = 1; 836 chunk->header.size_in_bytes = queue_info_size + queue_event_size + 837 sizeof(*chunk); 838 839 chunk->queue_info_table_record_count = rgp_queue_info->record_count; 840 chunk->queue_info_table_size = queue_info_size; 841 chunk->queue_event_table_record_count = rgp_queue_event->record_count; 842 chunk->queue_event_table_size = queue_event_size; 843} 844 845/** 846 * SQTT clock calibration info. 847 */ 848struct sqtt_file_chunk_clock_calibration { 849 struct sqtt_file_chunk_header header; 850 uint64_t cpu_timestamp; 851 uint64_t gpu_timestamp; 852 uint64_t reserved; 853}; 854 855static_assert(sizeof(struct sqtt_file_chunk_clock_calibration) == 40, 856 "sqtt_file_chunk_clock_calibration doesn't match RGP spec"); 857 858static void 859ac_sqtt_fill_clock_calibration(struct sqtt_file_chunk_clock_calibration *chunk, 860 int32_t chunk_index) 861{ 862 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_CLOCK_CALIBRATION; 863 chunk->header.chunk_id.index = chunk_index; 864 chunk->header.major_version = 0; 865 chunk->header.minor_version = 0; 866 chunk->header.size_in_bytes = sizeof(*chunk); 867} 868 869/* Below values are from from llvm project 870 * llvm/include/llvm/BinaryFormat/ELF.h 871 */ 872enum elf_gfxip_level 873{ 874 EF_AMDGPU_MACH_AMDGCN_GFX801 = 0x028, 875 EF_AMDGPU_MACH_AMDGCN_GFX900 = 0x02c, 876 EF_AMDGPU_MACH_AMDGCN_GFX1010 = 0x033, 877 EF_AMDGPU_MACH_AMDGCN_GFX1030 = 0x036, 878}; 879 880static enum elf_gfxip_level ac_gfx_level_to_elf_gfxip_level(enum amd_gfx_level gfx_level) 881{ 882 switch (gfx_level) { 883 case GFX8: 884 return EF_AMDGPU_MACH_AMDGCN_GFX801; 885 case GFX9: 886 return EF_AMDGPU_MACH_AMDGCN_GFX900; 887 case GFX10: 888 return EF_AMDGPU_MACH_AMDGCN_GFX1010; 889 case GFX10_3: 890 return EF_AMDGPU_MACH_AMDGCN_GFX1030; 891 default: 892 unreachable("Invalid gfx level"); 893 } 894} 895 896/** 897 * SQTT SPM DB info. 898 */ 899struct sqtt_spm_counter_info { 900 enum ac_pc_gpu_block block; 901 uint32_t instance; 902 uint32_t data_offset; /* offset of counter from the beginning of the chunk */ 903 uint32_t event_index; /* index of counter within the block */ 904}; 905 906struct sqtt_file_chunk_spm_db { 907 struct sqtt_file_chunk_header header; 908 uint32_t flags; 909 uint32_t num_timestamps; 910 uint32_t num_spm_counter_info; 911 uint32_t sample_interval; 912}; 913 914static_assert(sizeof(struct sqtt_file_chunk_spm_db) == 32, 915 "sqtt_file_chunk_spm_db doesn't match RGP spec"); 916 917static void ac_sqtt_fill_spm_db(const struct ac_spm_trace_data *spm_trace, 918 struct sqtt_file_chunk_spm_db *chunk, 919 uint32_t num_samples, 920 uint32_t chunk_size) 921{ 922 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_SPM_DB; 923 chunk->header.chunk_id.index = 0; 924 chunk->header.major_version = 1; 925 chunk->header.minor_version = 3; 926 chunk->header.size_in_bytes = chunk_size; 927 928 chunk->flags = 0; 929 chunk->num_timestamps = num_samples; 930 chunk->num_spm_counter_info = spm_trace->num_counters; 931 chunk->sample_interval = spm_trace->sample_interval; 932} 933 934static void ac_sqtt_dump_spm(const struct ac_spm_trace_data *spm_trace, 935 size_t file_offset, 936 FILE *output) 937{ 938 uint32_t sample_size_in_bytes = ac_spm_get_sample_size(spm_trace); 939 uint32_t num_samples = ac_spm_get_num_samples(spm_trace); 940 uint8_t *spm_data_ptr = (uint8_t *)spm_trace->ptr; 941 struct sqtt_file_chunk_spm_db spm_db; 942 size_t file_spm_db_offset = file_offset; 943 944 fseek(output, sizeof(struct sqtt_file_chunk_spm_db), SEEK_CUR); 945 file_offset += sizeof(struct sqtt_file_chunk_spm_db); 946 947 /* Skip the reserved 32 bytes of data at beginning. */ 948 spm_data_ptr += 32; 949 950 /* SPM timestamps. */ 951 uint32_t sample_size_in_qwords = sample_size_in_bytes / sizeof(uint64_t); 952 uint64_t *timestamp_ptr = (uint64_t *)spm_data_ptr; 953 954 for (uint32_t s = 0; s < num_samples; s++) { 955 uint64_t index = s * sample_size_in_qwords; 956 uint64_t timestamp = timestamp_ptr[index]; 957 958 file_offset += sizeof(timestamp); 959 fwrite(×tamp, sizeof(timestamp), 1, output); 960 } 961 962 /* SPM counter info. */ 963 uint64_t counter_values_size = num_samples * sizeof(uint16_t); 964 uint64_t counter_values_offset = num_samples * sizeof(uint64_t) + 965 spm_trace->num_counters * sizeof(struct sqtt_spm_counter_info); 966 967 for (uint32_t c = 0; c < spm_trace->num_counters; c++) { 968 struct sqtt_spm_counter_info cntr_info = { 969 .block = spm_trace->counters[c].gpu_block, 970 .instance = spm_trace->counters[c].instance, 971 .data_offset = counter_values_offset, 972 .event_index = spm_trace->counters[c].event_id, 973 }; 974 975 file_offset += sizeof(cntr_info); 976 fwrite(&cntr_info, sizeof(cntr_info), 1, output); 977 978 counter_values_offset += counter_values_size; 979 } 980 981 /* SPM counter values. */ 982 uint32_t sample_size_in_hwords = sample_size_in_bytes / sizeof(uint16_t); 983 uint16_t *counter_values_ptr = (uint16_t *)spm_data_ptr; 984 985 for (uint32_t c = 0; c < spm_trace->num_counters; c++) { 986 uint64_t offset = spm_trace->counters[c].offset; 987 988 for (uint32_t s = 0; s < num_samples; s++) { 989 uint64_t index = offset + (s * sample_size_in_hwords); 990 uint16_t value = counter_values_ptr[index]; 991 992 file_offset += sizeof(value); 993 fwrite(&value, sizeof(value), 1, output); 994 } 995 } 996 997 /* SQTT SPM DB chunk. */ 998 ac_sqtt_fill_spm_db(spm_trace, &spm_db, num_samples, 999 file_offset - file_spm_db_offset); 1000 fseek(output, file_spm_db_offset, SEEK_SET); 1001 fwrite(&spm_db, sizeof(struct sqtt_file_chunk_spm_db), 1, output); 1002 fseek(output, file_offset, SEEK_SET); 1003} 1004 1005#ifndef _WIN32 1006static void ac_sqtt_dump_data(struct radeon_info *rad_info, 1007 struct ac_thread_trace *thread_trace, 1008 const struct ac_spm_trace_data *spm_trace, 1009 FILE *output) 1010{ 1011 struct ac_thread_trace_data *thread_trace_data = thread_trace->data; 1012 struct sqtt_file_chunk_asic_info asic_info = {0}; 1013 struct sqtt_file_chunk_cpu_info cpu_info = {0}; 1014 struct sqtt_file_chunk_api_info api_info = {0}; 1015 struct sqtt_file_header header = {0}; 1016 size_t file_offset = 0; 1017 struct rgp_code_object *rgp_code_object = 1018 &thread_trace_data->rgp_code_object; 1019 struct rgp_loader_events *rgp_loader_events = 1020 &thread_trace_data->rgp_loader_events; 1021 struct rgp_pso_correlation *rgp_pso_correlation = 1022 &thread_trace_data->rgp_pso_correlation; 1023 struct rgp_queue_info *rgp_queue_info = &thread_trace_data->rgp_queue_info; 1024 struct rgp_queue_event *rgp_queue_event = &thread_trace_data->rgp_queue_event; 1025 struct rgp_clock_calibration *rgp_clock_calibration = &thread_trace_data->rgp_clock_calibration; 1026 1027 /* SQTT header file. */ 1028 ac_sqtt_fill_header(&header); 1029 file_offset += sizeof(header); 1030 fwrite(&header, sizeof(header), 1, output); 1031 1032 /* SQTT cpu chunk. */ 1033 ac_sqtt_fill_cpu_info(&cpu_info); 1034 file_offset += sizeof(cpu_info); 1035 fwrite(&cpu_info, sizeof(cpu_info), 1, output); 1036 1037 /* SQTT asic chunk. */ 1038 ac_sqtt_fill_asic_info(rad_info, &asic_info); 1039 file_offset += sizeof(asic_info); 1040 fwrite(&asic_info, sizeof(asic_info), 1, output); 1041 1042 /* SQTT api chunk. */ 1043 ac_sqtt_fill_api_info(&api_info); 1044 file_offset += sizeof(api_info); 1045 fwrite(&api_info, sizeof(api_info), 1, output); 1046 1047 /* SQTT code object database chunk. */ 1048 if (rgp_code_object->record_count) { 1049 size_t file_code_object_offset = file_offset; 1050 struct sqtt_file_chunk_code_object_database code_object; 1051 struct sqtt_code_object_database_record code_object_record; 1052 uint32_t elf_size_calc = 0; 1053 uint32_t flags = ac_gfx_level_to_elf_gfxip_level(rad_info->gfx_level); 1054 1055 fseek(output, sizeof(struct sqtt_file_chunk_code_object_database), SEEK_CUR); 1056 file_offset += sizeof(struct sqtt_file_chunk_code_object_database); 1057 list_for_each_entry_safe(struct rgp_code_object_record, record, 1058 &rgp_code_object->record, list) { 1059 fseek(output, sizeof(struct sqtt_code_object_database_record), SEEK_CUR); 1060 ac_rgp_file_write_elf_object(output, file_offset + 1061 sizeof(struct sqtt_code_object_database_record), 1062 record, &elf_size_calc, flags); 1063 /* Align to 4 bytes per the RGP file spec. */ 1064 code_object_record.size = ALIGN(elf_size_calc, 4); 1065 fseek(output, file_offset, SEEK_SET); 1066 fwrite(&code_object_record, sizeof(struct sqtt_code_object_database_record), 1067 1, output); 1068 file_offset += (sizeof(struct sqtt_code_object_database_record) + 1069 code_object_record.size); 1070 fseek(output, file_offset, SEEK_SET); 1071 } 1072 ac_sqtt_fill_code_object(rgp_code_object, &code_object, 1073 file_code_object_offset, 1074 file_offset - file_code_object_offset); 1075 fseek(output, file_code_object_offset, SEEK_SET); 1076 fwrite(&code_object, sizeof(struct sqtt_file_chunk_code_object_database), 1, output); 1077 fseek(output, file_offset, SEEK_SET); 1078 } 1079 1080 /* SQTT code object loader events chunk. */ 1081 if (rgp_loader_events->record_count) { 1082 struct sqtt_file_chunk_code_object_loader_events loader_events; 1083 1084 ac_sqtt_fill_loader_events(rgp_loader_events, &loader_events, 1085 file_offset); 1086 fwrite(&loader_events, sizeof(struct sqtt_file_chunk_code_object_loader_events), 1087 1, output); 1088 file_offset += sizeof(struct sqtt_file_chunk_code_object_loader_events); 1089 list_for_each_entry_safe(struct rgp_loader_events_record, record, 1090 &rgp_loader_events->record, list) { 1091 fwrite(record, sizeof(struct sqtt_code_object_loader_events_record), 1, output); 1092 } 1093 file_offset += (rgp_loader_events->record_count * 1094 sizeof(struct sqtt_code_object_loader_events_record)); 1095 } 1096 1097 /* SQTT pso correlation chunk. */ 1098 if (rgp_pso_correlation->record_count) { 1099 struct sqtt_file_chunk_pso_correlation pso_correlation; 1100 1101 ac_sqtt_fill_pso_correlation(rgp_pso_correlation, 1102 &pso_correlation, file_offset); 1103 fwrite(&pso_correlation, sizeof(struct sqtt_file_chunk_pso_correlation), 1, 1104 output); 1105 file_offset += sizeof(struct sqtt_file_chunk_pso_correlation); 1106 list_for_each_entry_safe(struct rgp_pso_correlation_record, record, 1107 &rgp_pso_correlation->record, list) { 1108 fwrite(record, sizeof(struct sqtt_pso_correlation_record), 1109 1, output); 1110 } 1111 file_offset += (rgp_pso_correlation->record_count * 1112 sizeof(struct sqtt_pso_correlation_record)); 1113 } 1114 1115 /* SQTT queue event timings. */ 1116 if (rgp_queue_info->record_count || rgp_queue_event->record_count) { 1117 struct sqtt_file_chunk_queue_event_timings queue_event_timings; 1118 1119 ac_sqtt_fill_queue_event_timings(rgp_queue_info, rgp_queue_event, 1120 &queue_event_timings); 1121 fwrite(&queue_event_timings, sizeof(struct sqtt_file_chunk_queue_event_timings), 1, 1122 output); 1123 file_offset += sizeof(struct sqtt_file_chunk_queue_event_timings); 1124 1125 /* Queue info. */ 1126 list_for_each_entry_safe(struct rgp_queue_info_record, record, 1127 &rgp_queue_info->record, list) { 1128 fwrite(record, sizeof(struct sqtt_queue_info_record), 1, output); 1129 } 1130 file_offset += (rgp_queue_info->record_count * 1131 sizeof(struct sqtt_queue_info_record)); 1132 1133 /* Queue event. */ 1134 list_for_each_entry_safe(struct rgp_queue_event_record, record, 1135 &rgp_queue_event->record, list) { 1136 fwrite(record, sizeof(struct sqtt_queue_event_record), 1, output); 1137 } 1138 file_offset += (rgp_queue_event->record_count * 1139 sizeof(struct sqtt_queue_event_record)); 1140 } 1141 1142 /* SQTT clock calibration. */ 1143 if (rgp_clock_calibration->record_count) { 1144 uint32_t num_records = 0; 1145 1146 list_for_each_entry_safe(struct rgp_clock_calibration_record, record, 1147 &rgp_clock_calibration->record, list) { 1148 struct sqtt_file_chunk_clock_calibration clock_calibration; 1149 memset(&clock_calibration, 0, sizeof(clock_calibration)); 1150 1151 ac_sqtt_fill_clock_calibration(&clock_calibration, num_records); 1152 1153 clock_calibration.cpu_timestamp = record->cpu_timestamp; 1154 clock_calibration.gpu_timestamp = record->gpu_timestamp; 1155 1156 fwrite(&clock_calibration, sizeof(struct sqtt_file_chunk_clock_calibration), 1, 1157 output); 1158 file_offset += sizeof(struct sqtt_file_chunk_clock_calibration); 1159 1160 num_records++; 1161 } 1162 } 1163 1164 if (thread_trace) { 1165 for (unsigned i = 0; i < thread_trace->num_traces; i++) { 1166 const struct ac_thread_trace_se *se = &thread_trace->traces[i]; 1167 const struct ac_thread_trace_info *info = &se->info; 1168 struct sqtt_file_chunk_sqtt_desc desc = {0}; 1169 struct sqtt_file_chunk_sqtt_data data = {0}; 1170 uint64_t size = info->cur_offset * 32; /* unit of 32 bytes */ 1171 1172 /* SQTT desc chunk. */ 1173 ac_sqtt_fill_sqtt_desc(rad_info, &desc, i, se->shader_engine, se->compute_unit); 1174 file_offset += sizeof(desc); 1175 fwrite(&desc, sizeof(desc), 1, output); 1176 1177 /* SQTT data chunk. */ 1178 ac_sqtt_fill_sqtt_data(&data, i, file_offset, size); 1179 file_offset += sizeof(data); 1180 fwrite(&data, sizeof(data), 1, output); 1181 1182 /* Copy thread trace data generated by the hardware. */ 1183 file_offset += size; 1184 fwrite(se->data_ptr, size, 1, output); 1185 } 1186 } 1187 1188 if (spm_trace) { 1189 ac_sqtt_dump_spm(spm_trace, file_offset, output); 1190 } 1191} 1192#endif 1193 1194int ac_dump_rgp_capture(struct radeon_info *info, 1195 struct ac_thread_trace *thread_trace, 1196 const struct ac_spm_trace_data *spm_trace) 1197{ 1198#ifdef _WIN32 1199 return -1; 1200#else 1201 char filename[2048]; 1202 struct tm now; 1203 time_t t; 1204 FILE *f; 1205 1206 t = time(NULL); 1207 now = *localtime(&t); 1208 1209 snprintf(filename, sizeof(filename), "/tmp/%s_%04d.%02d.%02d_%02d.%02d.%02d.rgp", 1210 util_get_process_name(), 1900 + now.tm_year, now.tm_mon + 1, now.tm_mday, now.tm_hour, 1211 now.tm_min, now.tm_sec); 1212 1213 f = fopen(filename, "w+"); 1214 if (!f) 1215 return -1; 1216 1217 ac_sqtt_dump_data(info, thread_trace, spm_trace, f); 1218 1219 fprintf(stderr, "RGP capture saved to '%s'\n", filename); 1220 1221 fclose(f); 1222 return 0; 1223#endif 1224} 1225