Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/amd/common/ac_rgp.c
7251 views
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_sqtt.h"
33
#include "ac_gpu_info.h"
34
#ifdef _WIN32
35
#define AMDGPU_VRAM_TYPE_UNKNOWN 0
36
#define AMDGPU_VRAM_TYPE_GDDR1 1
37
#define AMDGPU_VRAM_TYPE_DDR2 2
38
#define AMDGPU_VRAM_TYPE_GDDR3 3
39
#define AMDGPU_VRAM_TYPE_GDDR4 4
40
#define AMDGPU_VRAM_TYPE_GDDR5 5
41
#define AMDGPU_VRAM_TYPE_HBM 6
42
#define AMDGPU_VRAM_TYPE_DDR3 7
43
#define AMDGPU_VRAM_TYPE_DDR4 8
44
#define AMDGPU_VRAM_TYPE_GDDR6 9
45
#define AMDGPU_VRAM_TYPE_DDR5 10
46
#else
47
#include "drm-uapi/amdgpu_drm.h"
48
#endif
49
50
#include <stdbool.h>
51
#include <string.h>
52
53
#define SQTT_FILE_MAGIC_NUMBER 0x50303042
54
#define SQTT_FILE_VERSION_MAJOR 1
55
#define SQTT_FILE_VERSION_MINOR 5
56
57
#define SQTT_GPU_NAME_MAX_SIZE 256
58
#define SQTT_MAX_NUM_SE 32
59
#define SQTT_SA_PER_SE 2
60
61
enum sqtt_version
62
{
63
SQTT_VERSION_NONE = 0x0,
64
SQTT_VERSION_1_0 = 0x1,
65
SQTT_VERSION_1_1 = 0x2,
66
SQTT_VERSION_2_0 = 0x3, /* GFX6 */
67
SQTT_VERSION_2_1 = 0x4, /* GFX7 */
68
SQTT_VERSION_2_2 = 0x5, /* GFX8 */
69
SQTT_VERSION_2_3 = 0x6, /* GFX9 */
70
SQTT_VERSION_2_4 = 0x7 /* GFX10+ */
71
};
72
73
/**
74
* SQTT chunks.
75
*/
76
enum sqtt_file_chunk_type
77
{
78
SQTT_FILE_CHUNK_TYPE_ASIC_INFO,
79
SQTT_FILE_CHUNK_TYPE_SQTT_DESC,
80
SQTT_FILE_CHUNK_TYPE_SQTT_DATA,
81
SQTT_FILE_CHUNK_TYPE_API_INFO,
82
SQTT_FILE_CHUNK_TYPE_RESERVED,
83
SQTT_FILE_CHUNK_TYPE_QUEUE_EVENT_TIMINGS,
84
SQTT_FILE_CHUNK_TYPE_CLOCK_CALIBRATION,
85
SQTT_FILE_CHUNK_TYPE_CPU_INFO,
86
SQTT_FILE_CHUNK_TYPE_SPM_DB,
87
SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_DATABASE,
88
SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_LOADER_EVENTS,
89
SQTT_FILE_CHUNK_TYPE_PSO_CORRELATION,
90
SQTT_FILE_CHUNK_TYPE_INSTRUMENTATION_TABLE,
91
SQTT_FILE_CHUNK_TYPE_COUNT
92
};
93
94
struct sqtt_file_chunk_id {
95
enum sqtt_file_chunk_type type : 8;
96
int32_t index : 8;
97
int32_t reserved : 16;
98
};
99
100
struct sqtt_file_chunk_header {
101
struct sqtt_file_chunk_id chunk_id;
102
uint16_t minor_version;
103
uint16_t major_version;
104
int32_t size_in_bytes;
105
int32_t padding;
106
};
107
108
/**
109
* SQTT file header.
110
*/
111
struct sqtt_file_header_flags {
112
union {
113
struct {
114
int32_t is_semaphore_queue_timing_etw : 1;
115
int32_t no_queue_semaphore_timestamps : 1;
116
int32_t reserved : 30;
117
};
118
119
uint32_t value;
120
};
121
};
122
123
struct sqtt_file_header {
124
uint32_t magic_number;
125
uint32_t version_major;
126
uint32_t version_minor;
127
struct sqtt_file_header_flags flags;
128
int32_t chunk_offset;
129
int32_t second;
130
int32_t minute;
131
int32_t hour;
132
int32_t day_in_month;
133
int32_t month;
134
int32_t year;
135
int32_t day_in_week;
136
int32_t day_in_year;
137
int32_t is_daylight_savings;
138
};
139
140
static_assert(sizeof(struct sqtt_file_header) == 56, "sqtt_file_header doesn't match RGP spec");
141
142
static void ac_sqtt_fill_header(struct sqtt_file_header *header)
143
{
144
struct tm *timep, result;
145
time_t raw_time;
146
147
header->magic_number = SQTT_FILE_MAGIC_NUMBER;
148
header->version_major = SQTT_FILE_VERSION_MAJOR;
149
header->version_minor = SQTT_FILE_VERSION_MINOR;
150
header->flags.value = 0;
151
header->flags.is_semaphore_queue_timing_etw = 1;
152
header->flags.no_queue_semaphore_timestamps = 0;
153
header->chunk_offset = sizeof(*header);
154
155
time(&raw_time);
156
timep = os_localtime(&raw_time, &result);
157
158
header->second = timep->tm_sec;
159
header->minute = timep->tm_min;
160
header->hour = timep->tm_hour;
161
header->day_in_month = timep->tm_mday;
162
header->month = timep->tm_mon;
163
header->year = timep->tm_year;
164
header->day_in_week = timep->tm_wday;
165
header->day_in_year = timep->tm_yday;
166
header->is_daylight_savings = timep->tm_isdst;
167
}
168
169
/**
170
* SQTT CPU info.
171
*/
172
struct sqtt_file_chunk_cpu_info {
173
struct sqtt_file_chunk_header header;
174
uint32_t vendor_id[4];
175
uint32_t processor_brand[12];
176
uint32_t reserved[2];
177
uint64_t cpu_timestamp_freq;
178
uint32_t clock_speed;
179
uint32_t num_logical_cores;
180
uint32_t num_physical_cores;
181
uint32_t system_ram_size;
182
};
183
184
static_assert(sizeof(struct sqtt_file_chunk_cpu_info) == 112,
185
"sqtt_file_chunk_cpu_info doesn't match RGP spec");
186
187
static void ac_sqtt_fill_cpu_info(struct sqtt_file_chunk_cpu_info *chunk)
188
{
189
uint32_t cpu_clock_speed_total = 0;
190
uint64_t system_ram_size = 0;
191
char line[1024];
192
FILE *f;
193
194
chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_CPU_INFO;
195
chunk->header.chunk_id.index = 0;
196
chunk->header.major_version = 0;
197
chunk->header.minor_version = 0;
198
chunk->header.size_in_bytes = sizeof(*chunk);
199
200
chunk->cpu_timestamp_freq = 1000000000; /* tick set to 1ns */
201
202
strncpy((char *)chunk->vendor_id, "Unknown", sizeof(chunk->vendor_id));
203
strncpy((char *)chunk->processor_brand, "Unknown", sizeof(chunk->processor_brand));
204
chunk->clock_speed = 0;
205
chunk->num_logical_cores = 0;
206
chunk->num_physical_cores = 0;
207
chunk->system_ram_size = 0;
208
if (os_get_total_physical_memory(&system_ram_size))
209
chunk->system_ram_size = system_ram_size / (1024 * 1024);
210
211
/* Parse cpuinfo to get more detailled information. */
212
f = fopen("/proc/cpuinfo", "r");
213
if (!f)
214
return;
215
216
while (fgets(line, sizeof(line), f)) {
217
char *str;
218
219
/* Parse vendor name. */
220
str = strstr(line, "vendor_id");
221
if (str) {
222
char *ptr = (char *)chunk->vendor_id;
223
char *v = strtok(str, ":");
224
v = strtok(NULL, ":");
225
strncpy(ptr, v + 1, sizeof(chunk->vendor_id) - 1);
226
ptr[sizeof(chunk->vendor_id) - 1] = '\0';
227
}
228
229
/* Parse processor name. */
230
str = strstr(line, "model name");
231
if (str) {
232
char *ptr = (char *)chunk->processor_brand;
233
char *v = strtok(str, ":");
234
v = strtok(NULL, ":");
235
strncpy(ptr, v + 1, sizeof(chunk->processor_brand) - 1);
236
ptr[sizeof(chunk->processor_brand) - 1] = '\0';
237
}
238
239
/* Parse the current CPU clock speed for each cores. */
240
str = strstr(line, "cpu MHz");
241
if (str) {
242
uint32_t v = 0;
243
if (sscanf(str, "cpu MHz : %d", &v) == 1)
244
cpu_clock_speed_total += v;
245
}
246
247
/* Parse the number of logical cores. */
248
str = strstr(line, "siblings");
249
if (str) {
250
uint32_t v = 0;
251
if (sscanf(str, "siblings : %d", &v) == 1)
252
chunk->num_logical_cores = v;
253
}
254
255
/* Parse the number of physical cores. */
256
str = strstr(line, "cpu cores");
257
if (str) {
258
uint32_t v = 0;
259
if (sscanf(str, "cpu cores : %d", &v) == 1)
260
chunk->num_physical_cores = v;
261
}
262
}
263
264
if (chunk->num_logical_cores)
265
chunk->clock_speed = cpu_clock_speed_total / chunk->num_logical_cores;
266
267
fclose(f);
268
}
269
270
/**
271
* SQTT ASIC info.
272
*/
273
enum sqtt_file_chunk_asic_info_flags
274
{
275
SQTT_FILE_CHUNK_ASIC_INFO_FLAG_SC_PACKER_NUMBERING = (1 << 0),
276
SQTT_FILE_CHUNK_ASIC_INFO_FLAG_PS1_EVENT_TOKENS_ENABLED = (1 << 1)
277
};
278
279
enum sqtt_gpu_type
280
{
281
SQTT_GPU_TYPE_UNKNOWN = 0x0,
282
SQTT_GPU_TYPE_INTEGRATED = 0x1,
283
SQTT_GPU_TYPE_DISCRETE = 0x2,
284
SQTT_GPU_TYPE_VIRTUAL = 0x3
285
};
286
287
enum sqtt_gfxip_level
288
{
289
SQTT_GFXIP_LEVEL_NONE = 0x0,
290
SQTT_GFXIP_LEVEL_GFXIP_6 = 0x1,
291
SQTT_GFXIP_LEVEL_GFXIP_7 = 0x2,
292
SQTT_GFXIP_LEVEL_GFXIP_8 = 0x3,
293
SQTT_GFXIP_LEVEL_GFXIP_8_1 = 0x4,
294
SQTT_GFXIP_LEVEL_GFXIP_9 = 0x5,
295
SQTT_GFXIP_LEVEL_GFXIP_10_1 = 0x7,
296
SQTT_GFXIP_LEVEL_GFXIP_10_3 = 0x9,
297
};
298
299
enum sqtt_memory_type
300
{
301
SQTT_MEMORY_TYPE_UNKNOWN = 0x0,
302
SQTT_MEMORY_TYPE_DDR = 0x1,
303
SQTT_MEMORY_TYPE_DDR2 = 0x2,
304
SQTT_MEMORY_TYPE_DDR3 = 0x3,
305
SQTT_MEMORY_TYPE_DDR4 = 0x4,
306
SQTT_MEMORY_TYPE_GDDR3 = 0x10,
307
SQTT_MEMORY_TYPE_GDDR4 = 0x11,
308
SQTT_MEMORY_TYPE_GDDR5 = 0x12,
309
SQTT_MEMORY_TYPE_GDDR6 = 0x13,
310
SQTT_MEMORY_TYPE_HBM = 0x20,
311
SQTT_MEMORY_TYPE_HBM2 = 0x21,
312
SQTT_MEMORY_TYPE_HBM3 = 0x22,
313
SQTT_MEMORY_TYPE_LPDDR4 = 0x30,
314
SQTT_MEMORY_TYPE_LPDDR5 = 0x31,
315
};
316
317
struct sqtt_file_chunk_asic_info {
318
struct sqtt_file_chunk_header header;
319
uint64_t flags;
320
uint64_t trace_shader_core_clock;
321
uint64_t trace_memory_clock;
322
int32_t device_id;
323
int32_t device_revision_id;
324
int32_t vgprs_per_simd;
325
int32_t sgprs_per_simd;
326
int32_t shader_engines;
327
int32_t compute_unit_per_shader_engine;
328
int32_t simd_per_compute_unit;
329
int32_t wavefronts_per_simd;
330
int32_t minimum_vgpr_alloc;
331
int32_t vgpr_alloc_granularity;
332
int32_t minimum_sgpr_alloc;
333
int32_t sgpr_alloc_granularity;
334
int32_t hardware_contexts;
335
enum sqtt_gpu_type gpu_type;
336
enum sqtt_gfxip_level gfxip_level;
337
int32_t gpu_index;
338
int32_t gds_size;
339
int32_t gds_per_shader_engine;
340
int32_t ce_ram_size;
341
int32_t ce_ram_size_graphics;
342
int32_t ce_ram_size_compute;
343
int32_t max_number_of_dedicated_cus;
344
int64_t vram_size;
345
int32_t vram_bus_width;
346
int32_t l2_cache_size;
347
int32_t l1_cache_size;
348
int32_t lds_size;
349
char gpu_name[SQTT_GPU_NAME_MAX_SIZE];
350
float alu_per_clock;
351
float texture_per_clock;
352
float prims_per_clock;
353
float pixels_per_clock;
354
uint64_t gpu_timestamp_frequency;
355
uint64_t max_shader_core_clock;
356
uint64_t max_memory_clock;
357
uint32_t memory_ops_per_clock;
358
enum sqtt_memory_type memory_chip_type;
359
uint32_t lds_granularity;
360
uint16_t cu_mask[SQTT_MAX_NUM_SE][SQTT_SA_PER_SE];
361
char reserved1[128];
362
char padding[4];
363
};
364
365
static_assert(sizeof(struct sqtt_file_chunk_asic_info) == 720,
366
"sqtt_file_chunk_asic_info doesn't match RGP spec");
367
368
static enum sqtt_gfxip_level ac_chip_class_to_sqtt_gfxip_level(enum chip_class chip_class)
369
{
370
switch (chip_class) {
371
case GFX6:
372
return SQTT_GFXIP_LEVEL_GFXIP_6;
373
case GFX7:
374
return SQTT_GFXIP_LEVEL_GFXIP_7;
375
case GFX8:
376
return SQTT_GFXIP_LEVEL_GFXIP_8;
377
case GFX9:
378
return SQTT_GFXIP_LEVEL_GFXIP_9;
379
case GFX10:
380
return SQTT_GFXIP_LEVEL_GFXIP_10_1;
381
case GFX10_3:
382
return SQTT_GFXIP_LEVEL_GFXIP_10_3;
383
default:
384
unreachable("Invalid chip class");
385
}
386
}
387
388
static enum sqtt_memory_type ac_vram_type_to_sqtt_memory_type(uint32_t vram_type)
389
{
390
switch (vram_type) {
391
case AMDGPU_VRAM_TYPE_UNKNOWN:
392
return SQTT_MEMORY_TYPE_UNKNOWN;
393
case AMDGPU_VRAM_TYPE_DDR2:
394
return SQTT_MEMORY_TYPE_DDR2;
395
case AMDGPU_VRAM_TYPE_DDR3:
396
return SQTT_MEMORY_TYPE_DDR3;
397
case AMDGPU_VRAM_TYPE_DDR4:
398
return SQTT_MEMORY_TYPE_DDR4;
399
case AMDGPU_VRAM_TYPE_GDDR5:
400
return SQTT_MEMORY_TYPE_GDDR5;
401
case AMDGPU_VRAM_TYPE_HBM:
402
return SQTT_MEMORY_TYPE_HBM;
403
case AMDGPU_VRAM_TYPE_GDDR6:
404
return SQTT_MEMORY_TYPE_GDDR6;
405
case AMDGPU_VRAM_TYPE_DDR5:
406
return SQTT_MEMORY_TYPE_LPDDR5;
407
case AMDGPU_VRAM_TYPE_GDDR1:
408
case AMDGPU_VRAM_TYPE_GDDR3:
409
case AMDGPU_VRAM_TYPE_GDDR4:
410
default:
411
unreachable("Invalid vram type");
412
}
413
}
414
415
static uint32_t ac_memory_ops_per_clock(uint32_t vram_type)
416
{
417
switch (vram_type) {
418
case AMDGPU_VRAM_TYPE_UNKNOWN:
419
return 0;
420
case AMDGPU_VRAM_TYPE_DDR2:
421
case AMDGPU_VRAM_TYPE_DDR3:
422
case AMDGPU_VRAM_TYPE_DDR4:
423
case AMDGPU_VRAM_TYPE_HBM:
424
return 2;
425
case AMDGPU_VRAM_TYPE_DDR5:
426
case AMDGPU_VRAM_TYPE_GDDR5:
427
return 4;
428
case AMDGPU_VRAM_TYPE_GDDR6:
429
return 16;
430
case AMDGPU_VRAM_TYPE_GDDR1:
431
case AMDGPU_VRAM_TYPE_GDDR3:
432
case AMDGPU_VRAM_TYPE_GDDR4:
433
default:
434
unreachable("Invalid vram type");
435
}
436
}
437
438
static void ac_sqtt_fill_asic_info(struct radeon_info *rad_info,
439
struct sqtt_file_chunk_asic_info *chunk)
440
{
441
bool has_wave32 = rad_info->chip_class >= GFX10;
442
443
chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_ASIC_INFO;
444
chunk->header.chunk_id.index = 0;
445
chunk->header.major_version = 0;
446
chunk->header.minor_version = 4;
447
chunk->header.size_in_bytes = sizeof(*chunk);
448
449
chunk->flags = 0;
450
451
/* All chips older than GFX9 are affected by the "SPI not
452
* differentiating pkr_id for newwave commands" bug.
453
*/
454
if (rad_info->chip_class < GFX9)
455
chunk->flags |= SQTT_FILE_CHUNK_ASIC_INFO_FLAG_SC_PACKER_NUMBERING;
456
457
/* Only FIJI and GFX9+ support PS1 events. */
458
if (rad_info->family == CHIP_FIJI || rad_info->chip_class >= GFX9)
459
chunk->flags |= SQTT_FILE_CHUNK_ASIC_INFO_FLAG_PS1_EVENT_TOKENS_ENABLED;
460
461
chunk->trace_shader_core_clock = rad_info->max_shader_clock * 1000000;
462
chunk->trace_memory_clock = rad_info->max_memory_clock * 1000000;
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_chip_class_to_sqtt_gfxip_level(rad_info->chip_class);
482
chunk->gpu_index = 0;
483
484
chunk->max_number_of_dedicated_cus = 0;
485
chunk->ce_ram_size = rad_info->ce_ram_size;
486
chunk->ce_ram_size_graphics = 0;
487
chunk->ce_ram_size_compute = 0;
488
489
chunk->vram_bus_width = rad_info->vram_bit_width;
490
chunk->vram_size = rad_info->vram_size;
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->chip_class >= 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->chip_class == 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_shader_clock * 1000000;
510
chunk->max_memory_clock = rad_info->max_memory_clock * 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 < 4; se++) {
516
for (unsigned sa = 0; sa < 2; sa++) {
517
chunk->cu_mask[se][sa] = rad_info->cu_mask[se][sa];
518
}
519
}
520
}
521
522
/**
523
* SQTT API info.
524
*/
525
enum 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
533
enum 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
540
enum 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
548
union 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
567
union 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
578
struct 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
591
static_assert(sizeof(struct sqtt_file_chunk_api_info) == 1064,
592
"sqtt_file_chunk_api_info doesn't match RGP spec");
593
594
static 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
609
struct sqtt_code_object_database_record {
610
uint32_t size;
611
};
612
613
struct 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
621
static void
622
ac_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
637
struct 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
645
struct 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
653
static void
654
ac_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
}
671
struct 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
677
struct 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
685
static void
686
ac_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
*/
706
struct 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
722
static_assert(sizeof(struct sqtt_file_chunk_sqtt_desc) == 32,
723
"sqtt_file_chunk_sqtt_desc doesn't match RGP spec");
724
725
static enum sqtt_version ac_chip_class_to_sqtt_version(enum chip_class chip_class)
726
{
727
switch (chip_class) {
728
case GFX6:
729
return SQTT_VERSION_2_0;
730
case GFX7:
731
return SQTT_VERSION_2_1;
732
case GFX8:
733
return SQTT_VERSION_2_2;
734
case GFX9:
735
return SQTT_VERSION_2_3;
736
case GFX10:
737
return SQTT_VERSION_2_4;
738
case GFX10_3:
739
return SQTT_VERSION_2_4;
740
default:
741
unreachable("Invalid chip class");
742
}
743
}
744
745
static void ac_sqtt_fill_sqtt_desc(struct radeon_info *info,
746
struct sqtt_file_chunk_sqtt_desc *chunk, int32_t chunk_index,
747
int32_t shader_engine_index, int32_t compute_unit_index)
748
{
749
chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_SQTT_DESC;
750
chunk->header.chunk_id.index = chunk_index;
751
chunk->header.major_version = 0;
752
chunk->header.minor_version = 2;
753
chunk->header.size_in_bytes = sizeof(*chunk);
754
755
chunk->sqtt_version =
756
ac_chip_class_to_sqtt_version(info->chip_class);
757
chunk->shader_engine_index = shader_engine_index;
758
chunk->v1.instrumentation_spec_version = 1;
759
chunk->v1.instrumentation_api_version = 0;
760
chunk->v1.compute_unit_index = compute_unit_index;
761
}
762
763
/**
764
* SQTT data info.
765
*/
766
struct sqtt_file_chunk_sqtt_data {
767
struct sqtt_file_chunk_header header;
768
int32_t offset; /* in bytes */
769
int32_t size; /* in bytes */
770
};
771
772
static_assert(sizeof(struct sqtt_file_chunk_sqtt_data) == 24,
773
"sqtt_file_chunk_sqtt_data doesn't match RGP spec");
774
775
static void ac_sqtt_fill_sqtt_data(struct sqtt_file_chunk_sqtt_data *chunk, int32_t chunk_index,
776
int32_t offset, int32_t size)
777
{
778
chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_SQTT_DATA;
779
chunk->header.chunk_id.index = chunk_index;
780
chunk->header.major_version = 0;
781
chunk->header.minor_version = 0;
782
chunk->header.size_in_bytes = sizeof(*chunk) + size;
783
784
chunk->offset = sizeof(*chunk) + offset;
785
chunk->size = size;
786
}
787
788
/* Below values are from from llvm project
789
* llvm/include/llvm/BinaryFormat/ELF.h
790
*/
791
enum elf_gfxip_level
792
{
793
EF_AMDGPU_MACH_AMDGCN_GFX600 = 0x020,
794
EF_AMDGPU_MACH_AMDGCN_GFX700 = 0x022,
795
EF_AMDGPU_MACH_AMDGCN_GFX801 = 0x028,
796
EF_AMDGPU_MACH_AMDGCN_GFX900 = 0x02c,
797
EF_AMDGPU_MACH_AMDGCN_GFX1010 = 0x033,
798
EF_AMDGPU_MACH_AMDGCN_GFX1030 = 0x036,
799
};
800
801
static enum elf_gfxip_level ac_chip_class_to_elf_gfxip_level(enum chip_class chip_class)
802
{
803
switch (chip_class) {
804
case GFX6:
805
return EF_AMDGPU_MACH_AMDGCN_GFX600;
806
case GFX7:
807
return EF_AMDGPU_MACH_AMDGCN_GFX700;
808
case GFX8:
809
return EF_AMDGPU_MACH_AMDGCN_GFX801;
810
case GFX9:
811
return EF_AMDGPU_MACH_AMDGCN_GFX900;
812
case GFX10:
813
return EF_AMDGPU_MACH_AMDGCN_GFX1010;
814
case GFX10_3:
815
return EF_AMDGPU_MACH_AMDGCN_GFX1030;
816
default:
817
unreachable("Invalid chip class");
818
}
819
}
820
821
static void ac_sqtt_dump_data(struct radeon_info *rad_info,
822
struct ac_thread_trace *thread_trace,
823
FILE *output)
824
{
825
struct ac_thread_trace_data *thread_trace_data = thread_trace->data;
826
struct sqtt_file_chunk_asic_info asic_info = {0};
827
struct sqtt_file_chunk_cpu_info cpu_info = {0};
828
struct sqtt_file_chunk_api_info api_info = {0};
829
struct sqtt_file_header header = {0};
830
size_t file_offset = 0;
831
struct rgp_code_object *rgp_code_object =
832
&thread_trace_data->rgp_code_object;
833
struct rgp_loader_events *rgp_loader_events =
834
&thread_trace_data->rgp_loader_events;
835
struct rgp_pso_correlation *rgp_pso_correlation =
836
&thread_trace_data->rgp_pso_correlation;
837
838
/* SQTT header file. */
839
ac_sqtt_fill_header(&header);
840
file_offset += sizeof(header);
841
fwrite(&header, sizeof(header), 1, output);
842
843
/* SQTT cpu chunk. */
844
ac_sqtt_fill_cpu_info(&cpu_info);
845
file_offset += sizeof(cpu_info);
846
fwrite(&cpu_info, sizeof(cpu_info), 1, output);
847
848
/* SQTT asic chunk. */
849
ac_sqtt_fill_asic_info(rad_info, &asic_info);
850
file_offset += sizeof(asic_info);
851
fwrite(&asic_info, sizeof(asic_info), 1, output);
852
853
/* SQTT api chunk. */
854
ac_sqtt_fill_api_info(&api_info);
855
file_offset += sizeof(api_info);
856
fwrite(&api_info, sizeof(api_info), 1, output);
857
858
/* SQTT code object database chunk. */
859
if (rgp_code_object->record_count) {
860
size_t file_code_object_offset = file_offset;
861
struct sqtt_file_chunk_code_object_database code_object;
862
struct sqtt_code_object_database_record code_object_record;
863
uint32_t elf_size_calc = 0;
864
uint32_t flags = ac_chip_class_to_elf_gfxip_level(rad_info->chip_class);
865
866
fseek(output, sizeof(struct sqtt_file_chunk_code_object_database), SEEK_CUR);
867
file_offset += sizeof(struct sqtt_file_chunk_code_object_database);
868
list_for_each_entry_safe(struct rgp_code_object_record, record,
869
&rgp_code_object->record, list) {
870
fseek(output, sizeof(struct sqtt_code_object_database_record), SEEK_CUR);
871
ac_rgp_file_write_elf_object(output, file_offset +
872
sizeof(struct sqtt_code_object_database_record),
873
record, &elf_size_calc, flags);
874
code_object_record.size = elf_size_calc;
875
fseek(output, file_offset, SEEK_SET);
876
fwrite(&code_object_record, sizeof(struct sqtt_code_object_database_record),
877
1, output);
878
file_offset += (sizeof(struct sqtt_code_object_database_record) +
879
elf_size_calc);
880
fseek(output, file_offset, SEEK_SET);
881
}
882
ac_sqtt_fill_code_object(rgp_code_object, &code_object,
883
file_code_object_offset,
884
file_offset - file_code_object_offset);
885
fseek(output, file_code_object_offset, SEEK_SET);
886
fwrite(&code_object, sizeof(struct sqtt_file_chunk_code_object_database), 1, output);
887
fseek(output, file_offset, SEEK_SET);
888
}
889
890
/* SQTT code object loader events chunk. */
891
if (rgp_loader_events->record_count) {
892
struct sqtt_file_chunk_code_object_loader_events loader_events;
893
894
ac_sqtt_fill_loader_events(rgp_loader_events, &loader_events,
895
file_offset);
896
fwrite(&loader_events, sizeof(struct sqtt_file_chunk_code_object_loader_events),
897
1, output);
898
file_offset += sizeof(struct sqtt_file_chunk_code_object_loader_events);
899
list_for_each_entry_safe(struct rgp_loader_events_record, record,
900
&rgp_loader_events->record, list) {
901
fwrite(record, sizeof(struct sqtt_code_object_loader_events_record), 1, output);
902
}
903
file_offset += (rgp_loader_events->record_count *
904
sizeof(struct sqtt_code_object_loader_events_record));
905
}
906
907
/* SQTT pso correlation chunk. */
908
if (rgp_pso_correlation->record_count) {
909
struct sqtt_file_chunk_pso_correlation pso_correlation;
910
911
ac_sqtt_fill_pso_correlation(rgp_pso_correlation,
912
&pso_correlation, file_offset);
913
fwrite(&pso_correlation, sizeof(struct sqtt_file_chunk_pso_correlation), 1,
914
output);
915
file_offset += sizeof(struct sqtt_file_chunk_pso_correlation);
916
list_for_each_entry_safe(struct rgp_pso_correlation_record, record,
917
&rgp_pso_correlation->record, list) {
918
fwrite(record, sizeof(struct sqtt_pso_correlation_record),
919
1, output);
920
}
921
file_offset += (rgp_pso_correlation->record_count *
922
sizeof(struct sqtt_pso_correlation_record));
923
}
924
925
if (thread_trace) {
926
for (unsigned i = 0; i < thread_trace->num_traces; i++) {
927
const struct ac_thread_trace_se *se = &thread_trace->traces[i];
928
const struct ac_thread_trace_info *info = &se->info;
929
struct sqtt_file_chunk_sqtt_desc desc = {0};
930
struct sqtt_file_chunk_sqtt_data data = {0};
931
uint64_t size = info->cur_offset * 32; /* unit of 32 bytes */
932
933
/* SQTT desc chunk. */
934
ac_sqtt_fill_sqtt_desc(rad_info, &desc, i, se->shader_engine, se->compute_unit);
935
file_offset += sizeof(desc);
936
fwrite(&desc, sizeof(desc), 1, output);
937
938
/* SQTT data chunk. */
939
ac_sqtt_fill_sqtt_data(&data, i, file_offset, size);
940
file_offset += sizeof(data);
941
fwrite(&data, sizeof(data), 1, output);
942
943
/* Copy thread trace data generated by the hardware. */
944
file_offset += size;
945
fwrite(se->data_ptr, size, 1, output);
946
}
947
}
948
}
949
950
int ac_dump_rgp_capture(struct radeon_info *info,
951
struct ac_thread_trace *thread_trace)
952
{
953
char filename[2048];
954
struct tm now;
955
time_t t;
956
FILE *f;
957
958
t = time(NULL);
959
now = *localtime(&t);
960
961
snprintf(filename, sizeof(filename), "/tmp/%s_%04d.%02d.%02d_%02d.%02d.%02d.rgp",
962
util_get_process_name(), 1900 + now.tm_year, now.tm_mon + 1, now.tm_mday, now.tm_hour,
963
now.tm_min, now.tm_sec);
964
965
f = fopen(filename, "w+");
966
if (!f)
967
return -1;
968
969
ac_sqtt_dump_data(info, thread_trace, f);
970
971
fprintf(stderr, "RGP capture saved to '%s'\n", filename);
972
973
fclose(f);
974
return 0;
975
}
976
977