xref: /third_party/mesa3d/src/amd/common/ac_rgp.c (revision bf215546)
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(&timestamp, 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