summaryrefslogtreecommitdiff
path: root/src/amd/common/ac_rgp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/amd/common/ac_rgp.c')
-rw-r--r--src/amd/common/ac_rgp.c554
1 files changed, 399 insertions, 155 deletions
diff --git a/src/amd/common/ac_rgp.c b/src/amd/common/ac_rgp.c
index 7d0d48a91c0..496bc739f69 100644
--- a/src/amd/common/ac_rgp.c
+++ b/src/amd/common/ac_rgp.c
@@ -2,24 +2,7 @@
* Copyright 2020 Advanced Micro Devices, Inc.
* Copyright © 2020 Valve Corporation
*
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
+ * SPDX-License-Identifier: MIT
*/
#include "ac_rgp.h"
@@ -29,23 +12,10 @@
#include "util/u_process.h"
#include "util/u_math.h"
+#include "ac_spm.h"
#include "ac_sqtt.h"
#include "ac_gpu_info.h"
-#ifdef _WIN32
-#define AMDGPU_VRAM_TYPE_UNKNOWN 0
-#define AMDGPU_VRAM_TYPE_GDDR1 1
-#define AMDGPU_VRAM_TYPE_DDR2 2
-#define AMDGPU_VRAM_TYPE_GDDR3 3
-#define AMDGPU_VRAM_TYPE_GDDR4 4
-#define AMDGPU_VRAM_TYPE_GDDR5 5
-#define AMDGPU_VRAM_TYPE_HBM 6
-#define AMDGPU_VRAM_TYPE_DDR3 7
-#define AMDGPU_VRAM_TYPE_DDR4 8
-#define AMDGPU_VRAM_TYPE_GDDR6 9
-#define AMDGPU_VRAM_TYPE_DDR5 10
-#else
-#include "drm-uapi/amdgpu_drm.h"
-#endif
+#include "amd_family.h"
#include <stdbool.h>
#include <string.h>
@@ -57,17 +27,15 @@
#define SQTT_GPU_NAME_MAX_SIZE 256
#define SQTT_MAX_NUM_SE 32
#define SQTT_SA_PER_SE 2
+#define SQTT_ACTIVE_PIXEL_PACKER_MASK_DWORDS 4
enum sqtt_version
{
SQTT_VERSION_NONE = 0x0,
- SQTT_VERSION_1_0 = 0x1,
- SQTT_VERSION_1_1 = 0x2,
- SQTT_VERSION_2_0 = 0x3, /* GFX6 */
- SQTT_VERSION_2_1 = 0x4, /* GFX7 */
SQTT_VERSION_2_2 = 0x5, /* GFX8 */
SQTT_VERSION_2_3 = 0x6, /* GFX9 */
- SQTT_VERSION_2_4 = 0x7 /* GFX10+ */
+ SQTT_VERSION_2_4 = 0x7, /* GFX10+ */
+ SQTT_VERSION_3_2 = 0xb, /* GFX11+ */
};
/**
@@ -111,9 +79,9 @@ struct sqtt_file_chunk_header {
struct sqtt_file_header_flags {
union {
struct {
- int32_t is_semaphore_queue_timing_etw : 1;
- int32_t no_queue_semaphore_timestamps : 1;
- int32_t reserved : 30;
+ uint32_t is_semaphore_queue_timing_etw : 1;
+ uint32_t no_queue_semaphore_timestamps : 1;
+ uint32_t reserved : 30;
};
uint32_t value;
@@ -208,7 +176,7 @@ static void ac_sqtt_fill_cpu_info(struct sqtt_file_chunk_cpu_info *chunk)
if (os_get_total_physical_memory(&system_ram_size))
chunk->system_ram_size = system_ram_size / (1024 * 1024);
- /* Parse cpuinfo to get more detailled information. */
+ /* Parse cpuinfo to get more detailed information. */
f = fopen("/proc/cpuinfo", "r");
if (!f)
return;
@@ -294,6 +262,7 @@ enum sqtt_gfxip_level
SQTT_GFXIP_LEVEL_GFXIP_9 = 0x5,
SQTT_GFXIP_LEVEL_GFXIP_10_1 = 0x7,
SQTT_GFXIP_LEVEL_GFXIP_10_3 = 0x9,
+ SQTT_GFXIP_LEVEL_GFXIP_11_0 = 0xc,
};
enum sqtt_memory_type
@@ -303,6 +272,7 @@ enum sqtt_memory_type
SQTT_MEMORY_TYPE_DDR2 = 0x2,
SQTT_MEMORY_TYPE_DDR3 = 0x3,
SQTT_MEMORY_TYPE_DDR4 = 0x4,
+ SQTT_MEMORY_TYPE_DDR5 = 0x5,
SQTT_MEMORY_TYPE_GDDR3 = 0x10,
SQTT_MEMORY_TYPE_GDDR4 = 0x11,
SQTT_MEMORY_TYPE_GDDR5 = 0x12,
@@ -359,19 +329,21 @@ struct sqtt_file_chunk_asic_info {
uint32_t lds_granularity;
uint16_t cu_mask[SQTT_MAX_NUM_SE][SQTT_SA_PER_SE];
char reserved1[128];
+ uint32_t active_pixel_packer_mask[SQTT_ACTIVE_PIXEL_PACKER_MASK_DWORDS];
+ char reserved2[16];
+ uint32_t gl1_cache_size;
+ uint32_t instruction_cache_size;
+ uint32_t scalar_cache_size;
+ uint32_t mall_cache_size;
char padding[4];
};
-static_assert(sizeof(struct sqtt_file_chunk_asic_info) == 720,
+static_assert(sizeof(struct sqtt_file_chunk_asic_info) == 768,
"sqtt_file_chunk_asic_info doesn't match RGP spec");
-static enum sqtt_gfxip_level ac_chip_class_to_sqtt_gfxip_level(enum chip_class chip_class)
+static enum sqtt_gfxip_level ac_gfx_level_to_sqtt_gfxip_level(enum amd_gfx_level gfx_level)
{
- switch (chip_class) {
- case GFX6:
- return SQTT_GFXIP_LEVEL_GFXIP_6;
- case GFX7:
- return SQTT_GFXIP_LEVEL_GFXIP_7;
+ switch (gfx_level) {
case GFX8:
return SQTT_GFXIP_LEVEL_GFXIP_8;
case GFX9:
@@ -380,70 +352,54 @@ static enum sqtt_gfxip_level ac_chip_class_to_sqtt_gfxip_level(enum chip_class c
return SQTT_GFXIP_LEVEL_GFXIP_10_1;
case GFX10_3:
return SQTT_GFXIP_LEVEL_GFXIP_10_3;
+ case GFX11:
+ return SQTT_GFXIP_LEVEL_GFXIP_11_0;
default:
- unreachable("Invalid chip class");
+ unreachable("Invalid gfx level");
}
}
static enum sqtt_memory_type ac_vram_type_to_sqtt_memory_type(uint32_t vram_type)
{
switch (vram_type) {
- case AMDGPU_VRAM_TYPE_UNKNOWN:
+ case AMD_VRAM_TYPE_UNKNOWN:
return SQTT_MEMORY_TYPE_UNKNOWN;
- case AMDGPU_VRAM_TYPE_DDR2:
+ case AMD_VRAM_TYPE_DDR2:
return SQTT_MEMORY_TYPE_DDR2;
- case AMDGPU_VRAM_TYPE_DDR3:
+ case AMD_VRAM_TYPE_DDR3:
return SQTT_MEMORY_TYPE_DDR3;
- case AMDGPU_VRAM_TYPE_DDR4:
+ case AMD_VRAM_TYPE_DDR4:
return SQTT_MEMORY_TYPE_DDR4;
- case AMDGPU_VRAM_TYPE_GDDR5:
+ case AMD_VRAM_TYPE_DDR5:
+ return SQTT_MEMORY_TYPE_DDR5;
+ case AMD_VRAM_TYPE_GDDR3:
+ return SQTT_MEMORY_TYPE_GDDR3;
+ case AMD_VRAM_TYPE_GDDR4:
+ return SQTT_MEMORY_TYPE_GDDR4;
+ case AMD_VRAM_TYPE_GDDR5:
return SQTT_MEMORY_TYPE_GDDR5;
- case AMDGPU_VRAM_TYPE_HBM:
- return SQTT_MEMORY_TYPE_HBM;
- case AMDGPU_VRAM_TYPE_GDDR6:
+ case AMD_VRAM_TYPE_GDDR6:
return SQTT_MEMORY_TYPE_GDDR6;
- case AMDGPU_VRAM_TYPE_DDR5:
+ case AMD_VRAM_TYPE_HBM:
+ return SQTT_MEMORY_TYPE_HBM;
+ case AMD_VRAM_TYPE_LPDDR4:
+ return SQTT_MEMORY_TYPE_LPDDR4;
+ case AMD_VRAM_TYPE_LPDDR5:
return SQTT_MEMORY_TYPE_LPDDR5;
- case AMDGPU_VRAM_TYPE_GDDR1:
- case AMDGPU_VRAM_TYPE_GDDR3:
- case AMDGPU_VRAM_TYPE_GDDR4:
default:
unreachable("Invalid vram type");
}
}
-static uint32_t ac_memory_ops_per_clock(uint32_t vram_type)
-{
- switch (vram_type) {
- case AMDGPU_VRAM_TYPE_UNKNOWN:
- return 0;
- case AMDGPU_VRAM_TYPE_DDR2:
- case AMDGPU_VRAM_TYPE_DDR3:
- case AMDGPU_VRAM_TYPE_DDR4:
- case AMDGPU_VRAM_TYPE_HBM:
- return 2;
- case AMDGPU_VRAM_TYPE_DDR5:
- case AMDGPU_VRAM_TYPE_GDDR5:
- return 4;
- case AMDGPU_VRAM_TYPE_GDDR6:
- return 16;
- case AMDGPU_VRAM_TYPE_GDDR1:
- case AMDGPU_VRAM_TYPE_GDDR3:
- case AMDGPU_VRAM_TYPE_GDDR4:
- default:
- unreachable("Invalid vram type");
- }
-}
-
-static void ac_sqtt_fill_asic_info(struct radeon_info *rad_info,
+static void ac_sqtt_fill_asic_info(const struct radeon_info *rad_info,
struct sqtt_file_chunk_asic_info *chunk)
{
- bool has_wave32 = rad_info->chip_class >= GFX10;
+ bool has_wave32 = rad_info->gfx_level >= GFX10;
chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_ASIC_INFO;
chunk->header.chunk_id.index = 0;
chunk->header.major_version = 0;
- chunk->header.minor_version = 4;
+ chunk->header.minor_version = 5;
chunk->header.size_in_bytes = sizeof(*chunk);
chunk->flags = 0;
@@ -451,15 +407,22 @@ static void ac_sqtt_fill_asic_info(struct radeon_info *rad_info,
/* All chips older than GFX9 are affected by the "SPI not
* differentiating pkr_id for newwave commands" bug.
*/
- if (rad_info->chip_class < GFX9)
+ if (rad_info->gfx_level < GFX9)
chunk->flags |= SQTT_FILE_CHUNK_ASIC_INFO_FLAG_SC_PACKER_NUMBERING;
- /* Only FIJI and GFX9+ support PS1 events. */
- if (rad_info->family == CHIP_FIJI || rad_info->chip_class >= GFX9)
+ /* Only GFX9+ support PS1 events. */
+ if (rad_info->gfx_level >= GFX9)
chunk->flags |= SQTT_FILE_CHUNK_ASIC_INFO_FLAG_PS1_EVENT_TOKENS_ENABLED;
- chunk->trace_shader_core_clock = rad_info->max_shader_clock * 1000000;
- chunk->trace_memory_clock = rad_info->max_memory_clock * 1000000;
+ chunk->trace_shader_core_clock = rad_info->max_gpu_freq_mhz * 1000000ull;
+ chunk->trace_memory_clock = rad_info->memory_freq_mhz * 1000000ull;
+
+ /* RGP gets very confused if these clocks are 0. The numbers here are for profile_peak on
+ * VGH since that is the chips where we've seen the need for this workaround. */
+ if (!chunk->trace_shader_core_clock)
+ chunk->trace_shader_core_clock = 1300000000;
+ if (!chunk->trace_memory_clock)
+ chunk->trace_memory_clock = 687000000;
chunk->device_id = rad_info->pci_id;
chunk->device_revision_id = rad_info->pci_rev_id;
@@ -468,7 +431,7 @@ static void ac_sqtt_fill_asic_info(struct radeon_info *rad_info,
chunk->shader_engines = rad_info->max_se;
chunk->compute_unit_per_shader_engine = rad_info->min_good_cu_per_sa * rad_info->max_sa_per_se;
chunk->simd_per_compute_unit = rad_info->num_simd_per_compute_unit;
- chunk->wavefronts_per_simd = rad_info->max_wave64_per_simd;
+ chunk->wavefronts_per_simd = rad_info->max_waves_per_simd;
chunk->minimum_vgpr_alloc = rad_info->min_wave64_vgpr_alloc;
chunk->vgpr_alloc_granularity = rad_info->wave64_vgpr_alloc_granularity * (has_wave32 ? 2 : 1);
@@ -478,20 +441,20 @@ static void ac_sqtt_fill_asic_info(struct radeon_info *rad_info,
chunk->hardware_contexts = 8;
chunk->gpu_type =
rad_info->has_dedicated_vram ? SQTT_GPU_TYPE_DISCRETE : SQTT_GPU_TYPE_INTEGRATED;
- chunk->gfxip_level = ac_chip_class_to_sqtt_gfxip_level(rad_info->chip_class);
+ chunk->gfxip_level = ac_gfx_level_to_sqtt_gfxip_level(rad_info->gfx_level);
chunk->gpu_index = 0;
chunk->max_number_of_dedicated_cus = 0;
- chunk->ce_ram_size = rad_info->ce_ram_size;
+ chunk->ce_ram_size = 0;
chunk->ce_ram_size_graphics = 0;
chunk->ce_ram_size_compute = 0;
- chunk->vram_bus_width = rad_info->vram_bit_width;
- chunk->vram_size = rad_info->vram_size;
+ chunk->vram_bus_width = rad_info->memory_bus_width;
+ chunk->vram_size = (uint64_t)rad_info->vram_size_kb * 1024;
chunk->l2_cache_size = rad_info->l2_cache_size;
- chunk->l1_cache_size = rad_info->l1_cache_size;
+ chunk->l1_cache_size = rad_info->tcp_cache_size;
chunk->lds_size = rad_info->lds_size_per_workgroup;
- if (rad_info->chip_class >= GFX10) {
+ if (rad_info->gfx_level >= GFX10) {
/* RGP expects the LDS size in CU mode. */
chunk->lds_size /= 2;
}
@@ -501,22 +464,27 @@ static void ac_sqtt_fill_asic_info(struct radeon_info *rad_info,
chunk->alu_per_clock = 0.0;
chunk->texture_per_clock = 0.0;
chunk->prims_per_clock = rad_info->max_se;
- if (rad_info->chip_class == GFX10)
+ if (rad_info->gfx_level == GFX10)
chunk->prims_per_clock *= 2;
chunk->pixels_per_clock = 0.0;
chunk->gpu_timestamp_frequency = rad_info->clock_crystal_freq * 1000;
- chunk->max_shader_core_clock = rad_info->max_shader_clock * 1000000;
- chunk->max_memory_clock = rad_info->max_memory_clock * 1000000;
+ chunk->max_shader_core_clock = rad_info->max_gpu_freq_mhz * 1000000;
+ chunk->max_memory_clock = rad_info->memory_freq_mhz * 1000000;
chunk->memory_ops_per_clock = ac_memory_ops_per_clock(rad_info->vram_type);
chunk->memory_chip_type = ac_vram_type_to_sqtt_memory_type(rad_info->vram_type);
chunk->lds_granularity = rad_info->lds_encode_granularity;
- for (unsigned se = 0; se < 4; se++) {
- for (unsigned sa = 0; sa < 2; sa++) {
+ for (unsigned se = 0; se < AMD_MAX_SE; se++) {
+ for (unsigned sa = 0; sa < AMD_MAX_SA_PER_SE; sa++) {
chunk->cu_mask[se][sa] = rad_info->cu_mask[se][sa];
}
}
+
+ chunk->gl1_cache_size = rad_info->l1_cache_size;
+ chunk->instruction_cache_size = rad_info->sqc_inst_cache_size;
+ chunk->scalar_cache_size = rad_info->sqc_scalar_cache_size;
+ chunk->mall_cache_size = rad_info->l3_cache_size_mb * 1024 * 1024;
}
/**
@@ -570,9 +538,8 @@ union sqtt_instruction_trace_data {
} api_pso_data;
struct {
- char start[256];
- char end[256];
- } user_marker_data;
+ uint32_t mask;
+ } shader_engine_filter;
};
struct sqtt_file_chunk_api_info {
@@ -588,7 +555,7 @@ struct sqtt_file_chunk_api_info {
union sqtt_instruction_trace_data instruction_trace_data;
};
-static_assert(sizeof(struct sqtt_file_chunk_api_info) == 1064,
+static_assert(sizeof(struct sqtt_file_chunk_api_info) == 560,
"sqtt_file_chunk_api_info doesn't match RGP spec");
static void ac_sqtt_fill_api_info(struct sqtt_file_chunk_api_info *chunk)
@@ -596,7 +563,7 @@ static void ac_sqtt_fill_api_info(struct sqtt_file_chunk_api_info *chunk)
chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_API_INFO;
chunk->header.chunk_id.index = 0;
chunk->header.major_version = 0;
- chunk->header.minor_version = 1;
+ chunk->header.minor_version = 2;
chunk->header.size_in_bytes = sizeof(*chunk);
chunk->api_type = SQTT_API_TYPE_VULKAN;
@@ -619,9 +586,9 @@ struct sqtt_file_chunk_code_object_database {
};
static void
-ac_sqtt_fill_code_object(struct rgp_code_object *rgp_code_object,
- struct sqtt_file_chunk_code_object_database *chunk,
- size_t file_offset, uint32_t chunk_size)
+ac_sqtt_fill_code_object(const struct rgp_code_object *rgp_code_object,
+ struct sqtt_file_chunk_code_object_database *chunk, size_t file_offset,
+ uint32_t chunk_size)
{
chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_DATABASE;
chunk->header.chunk_id.index = 0;
@@ -651,7 +618,7 @@ struct sqtt_file_chunk_code_object_loader_events {
};
static void
-ac_sqtt_fill_loader_events(struct rgp_loader_events *rgp_loader_events,
+ac_sqtt_fill_loader_events(const struct rgp_loader_events *rgp_loader_events,
struct sqtt_file_chunk_code_object_loader_events *chunk,
size_t file_offset)
{
@@ -683,9 +650,8 @@ struct sqtt_file_chunk_pso_correlation {
};
static void
-ac_sqtt_fill_pso_correlation(struct rgp_pso_correlation *rgp_pso_correlation,
- struct sqtt_file_chunk_pso_correlation *chunk,
- size_t file_offset)
+ac_sqtt_fill_pso_correlation(const struct rgp_pso_correlation *rgp_pso_correlation,
+ struct sqtt_file_chunk_pso_correlation *chunk, size_t file_offset)
{
chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_PSO_CORRELATION;
chunk->header.chunk_id.index = 0;
@@ -722,13 +688,9 @@ struct sqtt_file_chunk_sqtt_desc {
static_assert(sizeof(struct sqtt_file_chunk_sqtt_desc) == 32,
"sqtt_file_chunk_sqtt_desc doesn't match RGP spec");
-static enum sqtt_version ac_chip_class_to_sqtt_version(enum chip_class chip_class)
+static enum sqtt_version ac_gfx_level_to_sqtt_version(enum amd_gfx_level gfx_level)
{
- switch (chip_class) {
- case GFX6:
- return SQTT_VERSION_2_0;
- case GFX7:
- return SQTT_VERSION_2_1;
+ switch (gfx_level) {
case GFX8:
return SQTT_VERSION_2_2;
case GFX9:
@@ -737,12 +699,14 @@ static enum sqtt_version ac_chip_class_to_sqtt_version(enum chip_class chip_clas
return SQTT_VERSION_2_4;
case GFX10_3:
return SQTT_VERSION_2_4;
+ case GFX11:
+ return SQTT_VERSION_3_2;
default:
- unreachable("Invalid chip class");
+ unreachable("Invalid gfx level");
}
}
-static void ac_sqtt_fill_sqtt_desc(struct radeon_info *info,
+static void ac_sqtt_fill_sqtt_desc(const struct radeon_info *info,
struct sqtt_file_chunk_sqtt_desc *chunk, int32_t chunk_index,
int32_t shader_engine_index, int32_t compute_unit_index)
{
@@ -753,7 +717,7 @@ static void ac_sqtt_fill_sqtt_desc(struct radeon_info *info,
chunk->header.size_in_bytes = sizeof(*chunk);
chunk->sqtt_version =
- ac_chip_class_to_sqtt_version(info->chip_class);
+ ac_gfx_level_to_sqtt_version(info->gfx_level);
chunk->shader_engine_index = shader_engine_index;
chunk->v1.instrumentation_spec_version = 1;
chunk->v1.instrumentation_api_version = 0;
@@ -785,26 +749,106 @@ static void ac_sqtt_fill_sqtt_data(struct sqtt_file_chunk_sqtt_data *chunk, int3
chunk->size = size;
}
+/**
+ * SQTT queue event timings info.
+ */
+struct sqtt_file_chunk_queue_event_timings {
+ struct sqtt_file_chunk_header header;
+ uint32_t queue_info_table_record_count;
+ uint32_t queue_info_table_size;
+ uint32_t queue_event_table_record_count;
+ uint32_t queue_event_table_size;
+};
+
+static_assert(sizeof(struct sqtt_file_chunk_queue_event_timings) == 32,
+ "sqtt_file_chunk_queue_event_timings doesn't match RGP spec");
+
+struct sqtt_queue_info_record {
+ uint64_t queue_id;
+ uint64_t queue_context;
+ struct sqtt_queue_hardware_info hardware_info;
+ uint32_t reserved;
+};
+
+static_assert(sizeof(struct sqtt_queue_info_record) == 24,
+ "sqtt_queue_info_record doesn't match RGP spec");
+
+struct sqtt_queue_event_record {
+ enum sqtt_queue_event_type event_type;
+ uint32_t sqtt_cb_id;
+ uint64_t frame_index;
+ uint32_t queue_info_index;
+ uint32_t submit_sub_index;
+ uint64_t api_id;
+ uint64_t cpu_timestamp;
+ uint64_t gpu_timestamps[2];
+};
+
+static_assert(sizeof(struct sqtt_queue_event_record) == 56,
+ "sqtt_queue_event_record doesn't match RGP spec");
+
+static void
+ac_sqtt_fill_queue_event_timings(const struct rgp_queue_info *rgp_queue_info,
+ const struct rgp_queue_event *rgp_queue_event,
+ struct sqtt_file_chunk_queue_event_timings *chunk)
+{
+ unsigned queue_info_size =
+ rgp_queue_info->record_count * sizeof(struct sqtt_queue_info_record);
+ unsigned queue_event_size =
+ rgp_queue_event->record_count * sizeof(struct sqtt_queue_event_record);
+
+ chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_QUEUE_EVENT_TIMINGS;
+ chunk->header.chunk_id.index = 0;
+ chunk->header.major_version = 1;
+ chunk->header.minor_version = 1;
+ chunk->header.size_in_bytes = queue_info_size + queue_event_size +
+ sizeof(*chunk);
+
+ chunk->queue_info_table_record_count = rgp_queue_info->record_count;
+ chunk->queue_info_table_size = queue_info_size;
+ chunk->queue_event_table_record_count = rgp_queue_event->record_count;
+ chunk->queue_event_table_size = queue_event_size;
+}
+
+/**
+ * SQTT clock calibration info.
+ */
+struct sqtt_file_chunk_clock_calibration {
+ struct sqtt_file_chunk_header header;
+ uint64_t cpu_timestamp;
+ uint64_t gpu_timestamp;
+ uint64_t reserved;
+};
+
+static_assert(sizeof(struct sqtt_file_chunk_clock_calibration) == 40,
+ "sqtt_file_chunk_clock_calibration doesn't match RGP spec");
+
+static void
+ac_sqtt_fill_clock_calibration(struct sqtt_file_chunk_clock_calibration *chunk,
+ int32_t chunk_index)
+{
+ chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_CLOCK_CALIBRATION;
+ chunk->header.chunk_id.index = chunk_index;
+ chunk->header.major_version = 0;
+ chunk->header.minor_version = 0;
+ chunk->header.size_in_bytes = sizeof(*chunk);
+}
+
/* Below values are from from llvm project
* llvm/include/llvm/BinaryFormat/ELF.h
*/
enum elf_gfxip_level
{
- EF_AMDGPU_MACH_AMDGCN_GFX600 = 0x020,
- EF_AMDGPU_MACH_AMDGCN_GFX700 = 0x022,
EF_AMDGPU_MACH_AMDGCN_GFX801 = 0x028,
EF_AMDGPU_MACH_AMDGCN_GFX900 = 0x02c,
EF_AMDGPU_MACH_AMDGCN_GFX1010 = 0x033,
EF_AMDGPU_MACH_AMDGCN_GFX1030 = 0x036,
+ EF_AMDGPU_MACH_AMDGCN_GFX1100 = 0x041,
};
-static enum elf_gfxip_level ac_chip_class_to_elf_gfxip_level(enum chip_class chip_class)
+static enum elf_gfxip_level ac_gfx_level_to_elf_gfxip_level(enum amd_gfx_level gfx_level)
{
- switch (chip_class) {
- case GFX6:
- return EF_AMDGPU_MACH_AMDGCN_GFX600;
- case GFX7:
- return EF_AMDGPU_MACH_AMDGCN_GFX700;
+ switch (gfx_level) {
case GFX8:
return EF_AMDGPU_MACH_AMDGCN_GFX801;
case GFX9:
@@ -813,27 +857,144 @@ static enum elf_gfxip_level ac_chip_class_to_elf_gfxip_level(enum chip_class chi
return EF_AMDGPU_MACH_AMDGCN_GFX1010;
case GFX10_3:
return EF_AMDGPU_MACH_AMDGCN_GFX1030;
+ case GFX11:
+ return EF_AMDGPU_MACH_AMDGCN_GFX1100;
default:
- unreachable("Invalid chip class");
+ unreachable("Invalid gfx level");
}
}
-static void ac_sqtt_dump_data(struct radeon_info *rad_info,
- struct ac_thread_trace *thread_trace,
- FILE *output)
+/**
+ * SQTT SPM DB info.
+ */
+struct sqtt_spm_counter_info {
+ enum ac_pc_gpu_block block;
+ uint32_t instance;
+ uint32_t event_index; /* index of counter within the block */
+ uint32_t data_offset; /* offset of counter from the beginning of the chunk */
+ uint32_t data_size; /* size in bytes of a single counter data item */
+};
+
+struct sqtt_file_chunk_spm_db {
+ struct sqtt_file_chunk_header header;
+ uint32_t flags;
+ uint32_t preamble_size;
+ uint32_t num_timestamps;
+ uint32_t num_spm_counter_info;
+ uint32_t spm_counter_info_size;
+ uint32_t sample_interval;
+};
+
+static_assert(sizeof(struct sqtt_file_chunk_spm_db) == 40,
+ "sqtt_file_chunk_spm_db doesn't match RGP spec");
+
+static void ac_sqtt_fill_spm_db(const struct ac_spm_trace *spm_trace,
+ struct sqtt_file_chunk_spm_db *chunk,
+ uint32_t num_samples,
+ uint32_t chunk_size)
+{
+ chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_SPM_DB;
+ chunk->header.chunk_id.index = 0;
+ chunk->header.major_version = 2;
+ chunk->header.minor_version = 0;
+ chunk->header.size_in_bytes = chunk_size;
+
+ chunk->flags = 0;
+ chunk->preamble_size = sizeof(struct sqtt_file_chunk_spm_db);
+ chunk->num_timestamps = num_samples;
+ chunk->num_spm_counter_info = spm_trace->num_counters;
+ chunk->spm_counter_info_size = sizeof(struct sqtt_spm_counter_info);
+ chunk->sample_interval = spm_trace->sample_interval;
+}
+
+static void ac_sqtt_dump_spm(const struct ac_spm_trace *spm_trace,
+ size_t file_offset,
+ FILE *output)
+{
+ uint32_t sample_size_in_bytes = spm_trace->sample_size_in_bytes;
+ uint32_t num_samples = spm_trace->num_samples;
+ uint8_t *spm_data_ptr = (uint8_t *)spm_trace->ptr;
+ struct sqtt_file_chunk_spm_db spm_db;
+ size_t file_spm_db_offset = file_offset;
+
+ fseek(output, sizeof(struct sqtt_file_chunk_spm_db), SEEK_CUR);
+ file_offset += sizeof(struct sqtt_file_chunk_spm_db);
+
+ /* Skip the reserved 32 bytes of data at beginning. */
+ spm_data_ptr += 32;
+
+ /* SPM timestamps. */
+ uint32_t sample_size_in_qwords = sample_size_in_bytes / sizeof(uint64_t);
+ uint64_t *timestamp_ptr = (uint64_t *)spm_data_ptr;
+
+ for (uint32_t s = 0; s < num_samples; s++) {
+ uint64_t index = s * sample_size_in_qwords;
+ uint64_t timestamp = timestamp_ptr[index];
+
+ file_offset += sizeof(timestamp);
+ fwrite(&timestamp, sizeof(timestamp), 1, output);
+ }
+
+ /* SPM counter info. */
+ uint64_t counter_values_size = num_samples * sizeof(uint16_t);
+ uint64_t counter_values_offset = num_samples * sizeof(uint64_t) +
+ spm_trace->num_counters * sizeof(struct sqtt_spm_counter_info);
+
+ for (uint32_t c = 0; c < spm_trace->num_counters; c++) {
+ struct sqtt_spm_counter_info cntr_info = {
+ .block = spm_trace->counters[c].gpu_block,
+ .instance = spm_trace->counters[c].instance,
+ .data_offset = counter_values_offset,
+ .data_size = sizeof(uint16_t),
+ .event_index = spm_trace->counters[c].event_id,
+ };
+
+ file_offset += sizeof(cntr_info);
+ fwrite(&cntr_info, sizeof(cntr_info), 1, output);
+
+ counter_values_offset += counter_values_size;
+ }
+
+ /* SPM counter values. */
+ uint32_t sample_size_in_hwords = sample_size_in_bytes / sizeof(uint16_t);
+ uint16_t *counter_values_ptr = (uint16_t *)spm_data_ptr;
+
+ for (uint32_t c = 0; c < spm_trace->num_counters; c++) {
+ uint64_t offset = spm_trace->counters[c].offset;
+
+ for (uint32_t s = 0; s < num_samples; s++) {
+ uint64_t index = offset + (s * sample_size_in_hwords);
+ uint16_t value = counter_values_ptr[index];
+
+ file_offset += sizeof(value);
+ fwrite(&value, sizeof(value), 1, output);
+ }
+ }
+
+ /* SQTT SPM DB chunk. */
+ ac_sqtt_fill_spm_db(spm_trace, &spm_db, num_samples,
+ file_offset - file_spm_db_offset);
+ fseek(output, file_spm_db_offset, SEEK_SET);
+ fwrite(&spm_db, sizeof(struct sqtt_file_chunk_spm_db), 1, output);
+ fseek(output, file_offset, SEEK_SET);
+}
+
+#if defined(USE_LIBELF)
+static void
+ac_sqtt_dump_data(const struct radeon_info *rad_info, struct ac_sqtt_trace *sqtt_trace,
+ const struct ac_spm_trace *spm_trace, FILE *output)
{
- struct ac_thread_trace_data *thread_trace_data = thread_trace->data;
struct sqtt_file_chunk_asic_info asic_info = {0};
struct sqtt_file_chunk_cpu_info cpu_info = {0};
struct sqtt_file_chunk_api_info api_info = {0};
struct sqtt_file_header header = {0};
size_t file_offset = 0;
- struct rgp_code_object *rgp_code_object =
- &thread_trace_data->rgp_code_object;
- struct rgp_loader_events *rgp_loader_events =
- &thread_trace_data->rgp_loader_events;
- struct rgp_pso_correlation *rgp_pso_correlation =
- &thread_trace_data->rgp_pso_correlation;
+ const struct rgp_code_object *rgp_code_object = sqtt_trace->rgp_code_object;
+ const struct rgp_loader_events *rgp_loader_events = sqtt_trace->rgp_loader_events;
+ const struct rgp_pso_correlation *rgp_pso_correlation = sqtt_trace->rgp_pso_correlation;
+ const struct rgp_queue_info *rgp_queue_info = sqtt_trace->rgp_queue_info;
+ const struct rgp_queue_event *rgp_queue_event = sqtt_trace->rgp_queue_event;
+ const struct rgp_clock_calibration *rgp_clock_calibration = sqtt_trace->rgp_clock_calibration;
/* SQTT header file. */
ac_sqtt_fill_header(&header);
@@ -861,7 +1022,7 @@ static void ac_sqtt_dump_data(struct radeon_info *rad_info,
struct sqtt_file_chunk_code_object_database code_object;
struct sqtt_code_object_database_record code_object_record;
uint32_t elf_size_calc = 0;
- uint32_t flags = ac_chip_class_to_elf_gfxip_level(rad_info->chip_class);
+ uint32_t flags = ac_gfx_level_to_elf_gfxip_level(rad_info->gfx_level);
fseek(output, sizeof(struct sqtt_file_chunk_code_object_database), SEEK_CUR);
file_offset += sizeof(struct sqtt_file_chunk_code_object_database);
@@ -871,12 +1032,13 @@ static void ac_sqtt_dump_data(struct radeon_info *rad_info,
ac_rgp_file_write_elf_object(output, file_offset +
sizeof(struct sqtt_code_object_database_record),
record, &elf_size_calc, flags);
- code_object_record.size = elf_size_calc;
+ /* Align to 4 bytes per the RGP file spec. */
+ code_object_record.size = ALIGN(elf_size_calc, 4);
fseek(output, file_offset, SEEK_SET);
fwrite(&code_object_record, sizeof(struct sqtt_code_object_database_record),
1, output);
file_offset += (sizeof(struct sqtt_code_object_database_record) +
- elf_size_calc);
+ code_object_record.size);
fseek(output, file_offset, SEEK_SET);
}
ac_sqtt_fill_code_object(rgp_code_object, &code_object,
@@ -922,10 +1084,82 @@ static void ac_sqtt_dump_data(struct radeon_info *rad_info,
sizeof(struct sqtt_pso_correlation_record));
}
- if (thread_trace) {
- for (unsigned i = 0; i < thread_trace->num_traces; i++) {
- const struct ac_thread_trace_se *se = &thread_trace->traces[i];
- const struct ac_thread_trace_info *info = &se->info;
+ /* SQTT queue event timings. */
+ if (rgp_queue_info->record_count || rgp_queue_event->record_count) {
+ struct sqtt_file_chunk_queue_event_timings queue_event_timings;
+
+ ac_sqtt_fill_queue_event_timings(rgp_queue_info, rgp_queue_event,
+ &queue_event_timings);
+ fwrite(&queue_event_timings, sizeof(struct sqtt_file_chunk_queue_event_timings), 1,
+ output);
+ file_offset += sizeof(struct sqtt_file_chunk_queue_event_timings);
+
+ /* Queue info. */
+ list_for_each_entry_safe(struct rgp_queue_info_record, record,
+ &rgp_queue_info->record, list) {
+ fwrite(record, sizeof(struct sqtt_queue_info_record), 1, output);
+ }
+ file_offset += (rgp_queue_info->record_count *
+ sizeof(struct sqtt_queue_info_record));
+
+ /* Queue event. */
+ list_for_each_entry_safe(struct rgp_queue_event_record, record,
+ &rgp_queue_event->record, list) {
+ struct sqtt_queue_event_record queue_event = {
+ .event_type = record->event_type,
+ .sqtt_cb_id = record->sqtt_cb_id,
+ .frame_index = record->frame_index,
+ .queue_info_index = record->queue_info_index,
+ .submit_sub_index = record->submit_sub_index,
+ .api_id = record->api_id,
+ .cpu_timestamp = record->cpu_timestamp,
+ };
+
+ switch (queue_event.event_type)
+ case SQTT_QUEUE_TIMING_EVENT_CMDBUF_SUBMIT: {
+ queue_event.gpu_timestamps[0] = *record->gpu_timestamps[0];
+ queue_event.gpu_timestamps[1] = *record->gpu_timestamps[1];
+ break;
+ case SQTT_QUEUE_TIMING_EVENT_PRESENT:
+ queue_event.gpu_timestamps[0] = *record->gpu_timestamps[0];
+ break;
+ default:
+ /* GPU timestamps are ignored for other queue events. */
+ break;
+ }
+
+ fwrite(&queue_event, sizeof(struct sqtt_queue_event_record), 1, output);
+ }
+ file_offset += (rgp_queue_event->record_count *
+ sizeof(struct sqtt_queue_event_record));
+ }
+
+ /* SQTT clock calibration. */
+ if (rgp_clock_calibration->record_count) {
+ uint32_t num_records = 0;
+
+ list_for_each_entry_safe(struct rgp_clock_calibration_record, record,
+ &rgp_clock_calibration->record, list) {
+ struct sqtt_file_chunk_clock_calibration clock_calibration;
+ memset(&clock_calibration, 0, sizeof(clock_calibration));
+
+ ac_sqtt_fill_clock_calibration(&clock_calibration, num_records);
+
+ clock_calibration.cpu_timestamp = record->cpu_timestamp;
+ clock_calibration.gpu_timestamp = record->gpu_timestamp;
+
+ fwrite(&clock_calibration, sizeof(struct sqtt_file_chunk_clock_calibration), 1,
+ output);
+ file_offset += sizeof(struct sqtt_file_chunk_clock_calibration);
+
+ num_records++;
+ }
+ }
+
+ if (sqtt_trace) {
+ for (unsigned i = 0; i < sqtt_trace->num_traces; i++) {
+ const struct ac_sqtt_data_se *se = &sqtt_trace->traces[i];
+ const struct ac_sqtt_data_info *info = &se->info;
struct sqtt_file_chunk_sqtt_desc desc = {0};
struct sqtt_file_chunk_sqtt_data data = {0};
uint64_t size = info->cur_offset * 32; /* unit of 32 bytes */
@@ -945,11 +1179,20 @@ static void ac_sqtt_dump_data(struct radeon_info *rad_info,
fwrite(se->data_ptr, size, 1, output);
}
}
+
+ if (spm_trace) {
+ ac_sqtt_dump_spm(spm_trace, file_offset, output);
+ }
}
+#endif
-int ac_dump_rgp_capture(struct radeon_info *info,
- struct ac_thread_trace *thread_trace)
+int
+ac_dump_rgp_capture(const struct radeon_info *info, struct ac_sqtt_trace *sqtt_trace,
+ const struct ac_spm_trace *spm_trace)
{
+#if !defined(USE_LIBELF)
+ return -1;
+#else
char filename[2048];
struct tm now;
time_t t;
@@ -966,10 +1209,11 @@ int ac_dump_rgp_capture(struct radeon_info *info,
if (!f)
return -1;
- ac_sqtt_dump_data(info, thread_trace, f);
+ ac_sqtt_dump_data(info, sqtt_trace, spm_trace, f);
fprintf(stderr, "RGP capture saved to '%s'\n", filename);
fclose(f);
return 0;
+#endif
}