aco: use nir_intrinsic_has_access
[mesa.git] / src / amd / vulkan / radv_rgp.c
1 /*
2 * Copyright © 2020 Valve Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23 #include <stdbool.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include "radv_private.h"
27
28 #include "util/u_process.h"
29
30 #include "drm-uapi/amdgpu_drm.h"
31
32 #define SQTT_FILE_MAGIC_NUMBER 0x50303042
33 #define SQTT_FILE_VERSION_MAJOR 1
34 #define SQTT_FILE_VERSION_MINOR 4
35
36 #define SQTT_GPU_NAME_MAX_SIZE 256
37 #define SQTT_MAX_NUM_SE 32
38 #define SQTT_SA_PER_SE 2
39
40 enum sqtt_version {
41 SQTT_VERSION_NONE = 0x0,
42 SQTT_VERSION_1_0 = 0x1,
43 SQTT_VERSION_1_1 = 0x2,
44 SQTT_VERSION_2_0 = 0x3, /* GFX6 */
45 SQTT_VERSION_2_1 = 0x4, /* GFX7 */
46 SQTT_VERSION_2_2 = 0x5, /* GFX8 */
47 SQTT_VERSION_2_3 = 0x6, /* GFX9 */
48 SQTT_VERSION_2_4 = 0x7 /* GFX10 */
49 };
50
51 /**
52 * SQTT chunks.
53 */
54 enum sqtt_file_chunk_type {
55 SQTT_FILE_CHUNK_TYPE_ASIC_INFO,
56 SQTT_FILE_CHUNK_TYPE_SQTT_DESC,
57 SQTT_FILE_CHUNK_TYPE_SQTT_DATA,
58 SQTT_FILE_CHUNK_TYPE_API_INFO,
59 SQTT_FILE_CHUNK_TYPE_ISA_DATABASE,
60 SQTT_FILE_CHUNK_TYPE_QUEUE_EVENT_TIMINGS,
61 SQTT_FILE_CHUNK_TYPE_CLOCK_CALIBRATION,
62 SQTT_FILE_CHUNK_TYPE_CPU_INFO,
63 SQTT_FILE_CHUNK_TYPE_SPM_DB,
64 SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_DATABASE,
65 SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_LOADER_EVENTS,
66 SQTT_FILE_CHUNK_TYPE_PSO_CORRELATION,
67 SQTT_FILE_CHUNK_TYPE_INSTRUMENTATION_TABLE,
68 SQTT_FILE_CHUNK_TYPE_COUNT
69 };
70
71 struct sqtt_file_chunk_id {
72 enum sqtt_file_chunk_type type : 8;
73 int32_t index : 8;
74 int32_t reserved : 16;
75 };
76
77 struct sqtt_file_chunk_header {
78 struct sqtt_file_chunk_id chunk_id;
79 uint16_t minor_version;
80 uint16_t major_version;
81 int32_t size_in_bytes;
82 int32_t padding;
83 };
84
85 /**
86 * SQTT file header.
87 */
88 struct sqtt_file_header_flags {
89 union {
90 struct {
91 int32_t is_semaphore_queue_timing_etw : 1;
92 int32_t no_queue_semaphore_timestamps : 1;
93 int32_t reserved : 30;
94 };
95
96 uint32_t value;
97 };
98 };
99
100 struct sqtt_file_header {
101 uint32_t magic_number;
102 uint32_t version_major;
103 uint32_t version_minor;
104 struct sqtt_file_header_flags flags;
105 int32_t chunk_offset;
106 int32_t second;
107 int32_t minute;
108 int32_t hour;
109 int32_t day_in_month;
110 int32_t month;
111 int32_t year;
112 int32_t day_in_week;
113 int32_t day_in_year;
114 int32_t is_daylight_savings;
115 };
116
117 static_assert(sizeof(struct sqtt_file_header) == 56,
118 "sqtt_file_header doesn't match RGP spec");
119
120 static void
121 radv_sqtt_fill_header(struct sqtt_file_header *header)
122 {
123 struct tm *timep, result;
124 time_t raw_time;
125
126 header->magic_number = SQTT_FILE_MAGIC_NUMBER;
127 header->version_major = SQTT_FILE_VERSION_MAJOR;
128 header->version_minor = SQTT_FILE_VERSION_MINOR;
129 header->flags.value = 0;
130 header->flags.is_semaphore_queue_timing_etw = 1;
131 header->flags.no_queue_semaphore_timestamps = 0;
132 header->chunk_offset = sizeof(*header);
133
134 time(&raw_time);
135 timep = localtime_r(&raw_time, &result);
136
137 header->second = timep->tm_sec;
138 header->minute = timep->tm_min;
139 header->hour = timep->tm_hour;
140 header->day_in_month = timep->tm_mday;
141 header->month = timep->tm_mon;
142 header->year = timep->tm_year;
143 header->day_in_week = timep->tm_wday;
144 header->day_in_year = timep->tm_yday;
145 header->is_daylight_savings = timep->tm_isdst;
146 }
147
148 /**
149 * SQTT CPU info.
150 */
151 struct sqtt_file_chunk_cpu_info {
152 struct sqtt_file_chunk_header header;
153 uint32_t vendor_id[4];
154 uint32_t processor_brand[12];
155 uint32_t reserved[2];
156 uint64_t cpu_timestamp_freq;
157 uint32_t clock_speed;
158 uint32_t num_logical_cores;
159 uint32_t num_physical_cores;
160 uint32_t system_ram_size;
161 };
162
163 static_assert(sizeof(struct sqtt_file_chunk_cpu_info) == 112,
164 "sqtt_file_chunk_cpu_info doesn't match RGP spec");
165
166 static void
167 radv_sqtt_fill_cpu_info(struct sqtt_file_chunk_cpu_info *chunk)
168 {
169 uint64_t system_ram_size = 0;
170
171 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_CPU_INFO;
172 chunk->header.chunk_id.index = 0;
173 chunk->header.major_version = 0;
174 chunk->header.minor_version = 0;
175 chunk->header.size_in_bytes = sizeof(*chunk);
176
177 chunk->cpu_timestamp_freq = 1000000000; /* tick set to 1ns */
178
179 /* TODO: fill with real info. */
180
181 strncpy((char *)chunk->vendor_id, "Unknown", sizeof(chunk->vendor_id));
182 strncpy((char *)chunk->processor_brand, "Unknown", sizeof(chunk->processor_brand));
183 chunk->clock_speed = 0;
184 chunk->num_logical_cores = 0;
185 chunk->num_physical_cores = 0;
186
187 chunk->system_ram_size = 0;
188 if (os_get_total_physical_memory(&system_ram_size))
189 chunk->system_ram_size = system_ram_size / (1024 * 1024);
190 }
191
192 /**
193 * SQTT ASIC info.
194 */
195 enum sqtt_file_chunk_asic_info_flags
196 {
197 SQTT_FILE_CHUNK_ASIC_INFO_FLAG_SC_PACKER_NUMBERING = (1 << 0),
198 SQTT_FILE_CHUNK_ASIC_INFO_FLAG_PS1_EVENT_TOKENS_ENABLED = (1 << 1)
199 };
200
201 enum sqtt_gpu_type {
202 SQTT_GPU_TYPE_UNKNOWN = 0x0,
203 SQTT_GPU_TYPE_INTEGRATED = 0x1,
204 SQTT_GPU_TYPE_DISCRETE = 0x2,
205 SQTT_GPU_TYPE_VIRTUAL = 0x3
206 };
207
208 enum sqtt_gfxip_level {
209 SQTT_GFXIP_LEVEL_NONE = 0x0,
210 SQTT_GFXIP_LEVEL_GFXIP_6 = 0x1,
211 SQTT_GFXIP_LEVEL_GFXIP_7 = 0x2,
212 SQTT_GFXIP_LEVEL_GFXIP_8 = 0x3,
213 SQTT_GFXIP_LEVEL_GFXIP_8_1 = 0x4,
214 SQTT_GFXIP_LEVEL_GFXIP_9 = 0x5,
215 SQTT_GFXIP_LEVEL_GFXIP_10_1 = 0x7,
216 };
217
218 enum sqtt_memory_type {
219 SQTT_MEMORY_TYPE_UNKNOWN = 0x0,
220 SQTT_MEMORY_TYPE_DDR = 0x1,
221 SQTT_MEMORY_TYPE_DDR2 = 0x2,
222 SQTT_MEMORY_TYPE_DDR3 = 0x3,
223 SQTT_MEMORY_TYPE_DDR4 = 0x4,
224 SQTT_MEMORY_TYPE_GDDR3 = 0x10,
225 SQTT_MEMORY_TYPE_GDDR4 = 0x11,
226 SQTT_MEMORY_TYPE_GDDR5 = 0x12,
227 SQTT_MEMORY_TYPE_GDDR6 = 0x13,
228 SQTT_MEMORY_TYPE_HBM = 0x20,
229 SQTT_MEMORY_TYPE_HBM2 = 0x21,
230 SQTT_MEMORY_TYPE_HBM3 = 0x22,
231 };
232
233 struct sqtt_file_chunk_asic_info {
234 struct sqtt_file_chunk_header header;
235 uint64_t flags;
236 uint64_t trace_shader_core_clock;
237 uint64_t trace_memory_clock;
238 int32_t device_id;
239 int32_t device_revision_id;
240 int32_t vgprs_per_simd;
241 int32_t sgprs_per_simd;
242 int32_t shader_engines;
243 int32_t compute_unit_per_shader_engine;
244 int32_t simd_per_compute_unit;
245 int32_t wavefronts_per_simd;
246 int32_t minimum_vgpr_alloc;
247 int32_t vgpr_alloc_granularity;
248 int32_t minimum_sgpr_alloc;
249 int32_t sgpr_alloc_granularity;
250 int32_t hardware_contexts;
251 enum sqtt_gpu_type gpu_type;
252 enum sqtt_gfxip_level gfxip_level;
253 int32_t gpu_index;
254 int32_t gds_size;
255 int32_t gds_per_shader_engine;
256 int32_t ce_ram_size;
257 int32_t ce_ram_size_graphics;
258 int32_t ce_ram_size_compute;
259 int32_t max_number_of_dedicated_cus;
260 int64_t vram_size;
261 int32_t vram_bus_width;
262 int32_t l2_cache_size;
263 int32_t l1_cache_size;
264 int32_t lds_size;
265 char gpu_name[SQTT_GPU_NAME_MAX_SIZE];
266 float alu_per_clock;
267 float texture_per_clock;
268 float prims_per_clock;
269 float pixels_per_clock;
270 uint64_t gpu_timestamp_frequency;
271 uint64_t max_shader_core_clock;
272 uint64_t max_memory_clock;
273 uint32_t memory_ops_per_clock;
274 enum sqtt_memory_type memory_chip_type;
275 uint32_t lds_granularity;
276 uint16_t cu_mask[SQTT_MAX_NUM_SE][SQTT_SA_PER_SE];
277 char reserved1[128];
278 char padding[4];
279 };
280
281 static_assert(sizeof(struct sqtt_file_chunk_asic_info) == 720,
282 "sqtt_file_chunk_asic_info doesn't match RGP spec");
283
284 static enum sqtt_gfxip_level
285 radv_chip_class_to_sqtt_gfxip_level(enum chip_class chip_class)
286 {
287 switch (chip_class) {
288 case GFX6:
289 return SQTT_GFXIP_LEVEL_GFXIP_6;
290 case GFX7:
291 return SQTT_GFXIP_LEVEL_GFXIP_7;
292 case GFX8:
293 return SQTT_GFXIP_LEVEL_GFXIP_8;
294 case GFX9:
295 return SQTT_GFXIP_LEVEL_GFXIP_9;
296 case GFX10:
297 return SQTT_GFXIP_LEVEL_GFXIP_10_1;
298 default:
299 unreachable("Invalid chip class");
300 }
301 }
302
303 static enum sqtt_memory_type
304 radv_vram_type_to_sqtt_memory_type(uint32_t vram_type)
305 {
306 switch (vram_type) {
307 case AMDGPU_VRAM_TYPE_UNKNOWN:
308 return SQTT_MEMORY_TYPE_UNKNOWN;
309 case AMDGPU_VRAM_TYPE_DDR2:
310 return SQTT_MEMORY_TYPE_DDR2;
311 case AMDGPU_VRAM_TYPE_DDR3:
312 return SQTT_MEMORY_TYPE_DDR3;
313 case AMDGPU_VRAM_TYPE_DDR4:
314 return SQTT_MEMORY_TYPE_DDR4;
315 case AMDGPU_VRAM_TYPE_GDDR5:
316 return SQTT_MEMORY_TYPE_GDDR5;
317 case AMDGPU_VRAM_TYPE_HBM:
318 return SQTT_MEMORY_TYPE_HBM;
319 case AMDGPU_VRAM_TYPE_GDDR6:
320 return SQTT_MEMORY_TYPE_GDDR6;
321 case AMDGPU_VRAM_TYPE_GDDR1:
322 case AMDGPU_VRAM_TYPE_GDDR3:
323 case AMDGPU_VRAM_TYPE_GDDR4:
324 default:
325 unreachable("Invalid vram type");
326 }
327 }
328
329 static void
330 radv_fill_sqtt_asic_info(struct radv_device *device,
331 struct sqtt_file_chunk_asic_info *chunk)
332 {
333 struct radeon_info *rad_info = &device->physical_device->rad_info;
334
335 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_ASIC_INFO;
336 chunk->header.chunk_id.index = 0;
337 chunk->header.major_version = 0;
338 chunk->header.minor_version = 4;
339 chunk->header.size_in_bytes = sizeof(*chunk);
340
341 chunk->flags = 0;
342
343 /* All chips older than GFX9 are affected by the "SPI not
344 * differentiating pkr_id for newwave commands" bug.
345 */
346 if (rad_info->chip_class < GFX9)
347 chunk->flags |= SQTT_FILE_CHUNK_ASIC_INFO_FLAG_SC_PACKER_NUMBERING;
348
349 /* Only FIJI and GFX9+ support PS1 events. */
350 if (rad_info->family == CHIP_FIJI || rad_info->chip_class >= GFX9)
351 chunk->flags |= SQTT_FILE_CHUNK_ASIC_INFO_FLAG_PS1_EVENT_TOKENS_ENABLED;
352
353 chunk->trace_shader_core_clock = rad_info->max_shader_clock * 1000000;
354 chunk->trace_memory_clock = rad_info->max_memory_clock * 1000000;
355
356 chunk->device_id = rad_info->pci_id;
357 chunk->device_revision_id = rad_info->pci_rev_id;
358 chunk->vgprs_per_simd = rad_info->num_physical_wave64_vgprs_per_simd;
359 chunk->sgprs_per_simd = rad_info->num_physical_sgprs_per_simd;
360 chunk->shader_engines = rad_info->max_se;
361 chunk->compute_unit_per_shader_engine = rad_info->min_good_cu_per_sa;
362 chunk->simd_per_compute_unit = rad_info->num_simd_per_compute_unit;
363 chunk->wavefronts_per_simd = rad_info->max_wave64_per_simd;
364
365 chunk->minimum_vgpr_alloc = rad_info->min_wave64_vgpr_alloc;
366 chunk->vgpr_alloc_granularity = rad_info->wave64_vgpr_alloc_granularity;
367 chunk->minimum_sgpr_alloc = rad_info->min_sgpr_alloc;
368 chunk->sgpr_alloc_granularity = rad_info->sgpr_alloc_granularity;
369
370 chunk->hardware_contexts = 8;
371 chunk->gpu_type = rad_info->has_dedicated_vram ? SQTT_GPU_TYPE_DISCRETE : SQTT_GPU_TYPE_INTEGRATED;
372 chunk->gfxip_level = radv_chip_class_to_sqtt_gfxip_level(rad_info->chip_class);
373 chunk->gpu_index = 0;
374
375 chunk->max_number_of_dedicated_cus = 0;
376 chunk->ce_ram_size = rad_info->ce_ram_size;
377 chunk->ce_ram_size_graphics = 0;
378 chunk->ce_ram_size_compute = 0;
379
380 chunk->vram_bus_width = rad_info->vram_bit_width;
381 chunk->vram_size = rad_info->vram_size;
382 chunk->l2_cache_size = rad_info->l2_cache_size;
383 chunk->l1_cache_size = rad_info->l1_cache_size;
384 chunk->lds_size = rad_info->lds_size_per_workgroup;
385
386 strncpy(chunk->gpu_name, device->physical_device->name, SQTT_GPU_NAME_MAX_SIZE);
387
388 chunk->alu_per_clock = 0.0;
389 chunk->texture_per_clock = 0.0;
390 chunk->prims_per_clock = 0.0;
391 chunk->pixels_per_clock = 0.0;
392
393 chunk->gpu_timestamp_frequency = rad_info->clock_crystal_freq * 1000;
394 chunk->max_shader_core_clock = rad_info->max_shader_clock * 1000000;
395 chunk->max_memory_clock = rad_info->max_memory_clock * 1000000;
396 chunk->memory_ops_per_clock = 0;
397 chunk->memory_chip_type = radv_vram_type_to_sqtt_memory_type(rad_info->vram_type);
398 chunk->lds_granularity = rad_info->lds_granularity;
399
400 for (unsigned se = 0; se < 4; se++) {
401 for (unsigned sa = 0; sa < 2; sa++) {
402 chunk->cu_mask[se][sa] = rad_info->cu_mask[se][sa];
403 }
404 }
405 }
406
407 /**
408 * SQTT API info.
409 */
410 enum sqtt_api_type {
411 SQTT_API_TYPE_DIRECTX_12,
412 SQTT_API_TYPE_VULKAN,
413 SQTT_API_TYPE_GENERIC,
414 SQTT_API_TYPE_OPENCL
415 };
416
417 enum sqtt_instruction_trace_mode
418 {
419 SQTT_INSTRUCTION_TRACE_DISABLED = 0x0,
420 SQTT_INSTRUCTION_TRACE_FULL_FRAME = 0x1,
421 SQTT_INSTRUCTION_TRACE_API_PSO = 0x2,
422 };
423
424 enum sqtt_profiling_mode {
425 SQTT_PROFILING_MODE_PRESENT = 0x0,
426 SQTT_PROFILING_MODE_USER_MARKERS = 0x1,
427 SQTT_PROFILING_MODE_INDEX = 0x2,
428 SQTT_PROFILING_MODE_TAG = 0x3,
429 };
430
431 union sqtt_profiling_mode_data {
432 struct {
433 char start[256];
434 char end[256];
435 } user_marker_profiling_data;
436
437 struct {
438 uint32_t start;
439 uint32_t end;
440 } index_profiling_data;
441
442 struct {
443 uint32_t begin_hi;
444 uint32_t begin_lo;
445 uint32_t end_hi;
446 uint32_t end_lo;
447 } tag_profiling_data;
448 };
449
450 union sqtt_instruction_trace_data {
451 struct {
452 uint64_t api_pso_filter;
453 } api_pso_data;
454
455 struct {
456 char start[256];
457 char end[256];
458 } user_marker_data;
459 };
460
461 struct sqtt_file_chunk_api_info {
462 struct sqtt_file_chunk_header header;
463 enum sqtt_api_type api_type;
464 uint16_t major_version;
465 uint16_t minor_version;
466 enum sqtt_profiling_mode profiling_mode;
467 uint32_t reserved;
468 union sqtt_profiling_mode_data profiling_mode_data;
469 enum sqtt_instruction_trace_mode instruction_trace_mode;
470 uint32_t reserved2;
471 union sqtt_instruction_trace_data instruction_trace_data;
472 };
473
474 static_assert(sizeof(struct sqtt_file_chunk_api_info) == 1064,
475 "sqtt_file_chunk_api_info doesn't match RGP spec");
476
477 static void
478 radv_sqtt_fill_api_info(struct sqtt_file_chunk_api_info *chunk)
479 {
480 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_API_INFO;
481 chunk->header.chunk_id.index = 0;
482 chunk->header.major_version = 0;
483 chunk->header.minor_version = 1;
484 chunk->header.size_in_bytes = sizeof(*chunk);
485
486 chunk->api_type = SQTT_API_TYPE_VULKAN;
487 chunk->major_version = 0;
488 chunk->minor_version = 0;
489 chunk->profiling_mode = SQTT_PROFILING_MODE_PRESENT;
490 chunk->instruction_trace_mode = SQTT_INSTRUCTION_TRACE_DISABLED;
491 }
492
493 /**
494 * SQTT desc info.
495 */
496 struct sqtt_file_chunk_sqtt_desc {
497 struct sqtt_file_chunk_header header;
498 int32_t shader_engine_index;
499 enum sqtt_version sqtt_version;
500 union {
501 struct {
502 int32_t instrumentation_version;
503 } v0;
504 struct {
505 int16_t instrumentation_spec_version;
506 int16_t instrumentation_api_version;
507 int32_t compute_unit_index;
508 } v1;
509 };
510 };
511
512 static_assert(sizeof(struct sqtt_file_chunk_sqtt_desc) == 32,
513 "sqtt_file_chunk_sqtt_desc doesn't match RGP spec");
514
515 static enum sqtt_version
516 radv_chip_class_to_sqtt_version(enum chip_class chip_class)
517 {
518 switch (chip_class) {
519 case GFX6:
520 return SQTT_VERSION_2_0;
521 case GFX7:
522 return SQTT_VERSION_2_1;
523 case GFX8:
524 return SQTT_VERSION_2_2;
525 case GFX9:
526 return SQTT_VERSION_2_3;
527 case GFX10:
528 return SQTT_VERSION_2_4;
529 default:
530 unreachable("Invalid chip class");
531 }
532 }
533
534 static void
535 radv_sqtt_fill_sqtt_desc(struct radv_device *device,
536 struct sqtt_file_chunk_sqtt_desc *chunk,
537 int32_t chunk_index,
538 int32_t shader_engine_index,
539 int32_t compute_unit_index)
540 {
541 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_SQTT_DESC;
542 chunk->header.chunk_id.index = chunk_index;
543 chunk->header.major_version = 0;
544 chunk->header.minor_version = 2;
545 chunk->header.size_in_bytes = sizeof(*chunk);
546
547 chunk->sqtt_version = radv_chip_class_to_sqtt_version(device->physical_device->rad_info.chip_class);
548 chunk->shader_engine_index = shader_engine_index;
549 chunk->v1.instrumentation_spec_version = 1;
550 chunk->v1.instrumentation_api_version = 0;
551 chunk->v1.compute_unit_index = compute_unit_index;
552 }
553
554 /**
555 * SQTT data info.
556 */
557 struct sqtt_file_chunk_sqtt_data {
558 struct sqtt_file_chunk_header header;
559 int32_t offset; /* in bytes */
560 int32_t size; /* in bytes */
561 };
562
563 static_assert(sizeof(struct sqtt_file_chunk_sqtt_data) == 24,
564 "sqtt_file_chunk_sqtt_data doesn't match RGP spec");
565
566 static void
567 radv_sqtt_fill_sqtt_data(struct sqtt_file_chunk_sqtt_data *chunk,
568 int32_t chunk_index, int32_t offset, int32_t size)
569 {
570 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_SQTT_DATA;
571 chunk->header.chunk_id.index = chunk_index;
572 chunk->header.major_version = 0;
573 chunk->header.minor_version = 0;
574 chunk->header.size_in_bytes = sizeof(*chunk) + size;
575
576 chunk->offset = sizeof(*chunk) + offset;
577 chunk->size = size;
578 }
579
580 static void
581 radv_sqtt_dump_data(struct radv_device *device,
582 const struct radv_thread_trace *thread_trace,
583 FILE *output)
584 {
585 struct sqtt_file_chunk_asic_info asic_info = {};
586 struct sqtt_file_chunk_cpu_info cpu_info = {};
587 struct sqtt_file_chunk_api_info api_info = {};
588 struct sqtt_file_header header = {};
589 size_t file_offset = 0;
590
591 /* SQTT header file. */
592 radv_sqtt_fill_header(&header);
593 file_offset += sizeof(header);
594 fwrite(&header, sizeof(header), 1, output);
595
596 /* SQTT cpu chunk. */
597 radv_sqtt_fill_cpu_info(&cpu_info);
598 file_offset += sizeof(cpu_info);
599 fwrite(&cpu_info, sizeof(cpu_info), 1, output);
600
601 /* SQTT asic chunk. */
602 radv_fill_sqtt_asic_info(device, &asic_info);
603 file_offset += sizeof(asic_info);
604 fwrite(&asic_info, sizeof(asic_info), 1, output);
605
606 /* SQTT api chunk. */
607 radv_sqtt_fill_api_info(&api_info);
608 file_offset += sizeof(api_info);
609 fwrite(&api_info, sizeof(api_info), 1, output);
610
611 if (thread_trace) {
612 for (unsigned i = 0; i < thread_trace->num_traces; i++) {
613 const struct radv_thread_trace_se *se = &thread_trace->traces[i];
614 const struct radv_thread_trace_info *info = &se->info;
615 struct sqtt_file_chunk_sqtt_desc desc = {};
616 struct sqtt_file_chunk_sqtt_data data = {};
617 uint64_t size = info->cur_offset * 32; /* unit of 32 bytes */
618
619 /* SQTT desc chunk. */
620 radv_sqtt_fill_sqtt_desc(device, &desc, i,
621 se->shader_engine,
622 se->compute_unit);
623 file_offset += sizeof(desc);
624 fwrite(&desc, sizeof(desc), 1, output);
625
626 /* SQTT data chunk. */
627 radv_sqtt_fill_sqtt_data(&data, i, file_offset, size);
628 file_offset += sizeof(data);
629 fwrite(&data, sizeof(data), 1, output);
630
631 /* Copy thread trace data generated by the hardware. */
632 file_offset += size;
633 fwrite(se->data_ptr, size, 1, output);
634 }
635 }
636 }
637
638 int
639 radv_dump_thread_trace(struct radv_device *device,
640 const struct radv_thread_trace *thread_trace)
641 {
642 char filename[2048];
643 struct tm now;
644 time_t t;
645 FILE *f;
646
647 t = time(NULL);
648 now = *localtime(&t);
649
650 snprintf(filename, sizeof(filename), "/tmp/%s_%04d.%02d.%02d_%02d.%02d.rgp",
651 util_get_process_name(), 1900 + now.tm_year, now.tm_mon + 1,
652 now.tm_mday, now.tm_hour, now.tm_min);
653
654 f = fopen(filename, "w+");
655 if (!f)
656 return -1;
657
658 radv_sqtt_dump_data(device, thread_trace, f);
659
660 fprintf(stderr, "Thread trace capture saved to '%s'\n", filename);
661
662 fclose(f);
663 return 0;
664 }
665