用法
版权 (c) 2018-2025 Advanced Micro Devices, Inc. 版权所有。 GPU Performance API 用法 本页提供了 GPUPerfAPI 库的概述。有关更多信息,请参阅 API 参考页。
从 GPA 3.x 迁移到 4.0
总结
GPA 4.0 的主要变化是计数器不再通过 GpaContext 暴露,而是通过 GpaSession 暴露。现在有两组不同的计数器,具体取决于创建会话时传递的 GpaSessionSampleType。并非所有硬件和所有渲染 API 都支持所有 GpaSessionSampleTypes,因此在创建 GpaContext 后,您应该调用 GpaGetSupportedSampleTypes(..) 来查询给定配置支持哪些 GpaSessionSampleTypes。GPU Performance API 的用户仍然只应查找 kGpaSessionSampleTypeDiscreteCounter 样本类型。其他样本类型将不提供支持。创建 GpaSession 后,您可以使用 GpaGetNumCounters(..) 和所有 GpaGetCounter*(..) 入口点来查询有关可用计数器的信息。
下面将提供一个可能的 GPA 3.x 系列 API 调用子集示例,然后是使用修改后的 GPA 4.0 入口点的类似调用系列。请注意,为清晰起见,此处未进行任何错误检查。
GPA 3.x 用法示例
GpaContextId context = nullptr;GpaOpenContext(api_context, kGpaOpenContextDefaultBit, &context);GpaUInt32 num_counters = 0;GpaGetNumCounters(context, &num_counters);for (GpaUInt32 i = 0; i < num_counters; ++i){ const char* name = nullptr; GpaUInt32 index = 0; const char* description = nullptr; const char* group = nullptr; GpaDataType data_type = kGpaDataTypeLast; GpaUsageType usage_type = kGpaUsageTypeList; GpaUuid uuid = {}; GpaCounterSampleType sample_type = kGpaCounterSampleTypeDiscrete;
GpaGetCounterName(context, i, &name); GpaGetCounterIndex(context, name, &index); assert(i == index); GpaGetCounterDescription(context, i, &description); GpaGetCounterDataType(context, i, &data_type); GpaGetCounterUsageType(context, i, &usage_type); GpaGetCounterUuid(context, i, &uuid); GpaGetCounterSampleType(context, i, &sample_type); assert(sample_type == kGpaCounterSampleTypeDiscrete);}GpaSessionId session = nullptr;GpaCreateSession(context, kGpaContextSampleTypeDiscreteCounter, &session);GpaUInt32 desired_counter_index = 0;GpaEnableCounter(session, desired_counter_index);GpaBeginSession(session);...类似 GPA 4.0 的用法示例
下面的代码中添加了注释,以解释新的代码更改。
GpaContextId context = nullptr;GpaOpenContext(api_context, kGpaOpenContextDefaultBit, &context);
// These next two lines and the following conditional ensure that discrete counters are supported// by the GpaContext for the current hardware and driver. In general the GpaOpenContext call above// will report an error if the hardware and driver are not supported at all, but in some rare cases// the discrete counters may not be supported while other sample types are supported.GpaContextSampleTypeFlags supported_sample_types = kGpaSessionSampleTypeLast;GpaGetSupportedSampleTypes(context, &supported_sample_types);
if (supported_sample_types & kGpaSessionSampleTypeDiscreteCounter != 0){ // The set of available counters are now dependent on the SampleType being collected within // the session, so the session must now be created prior to querying for the available counters. GpaSessionId session = nullptr; GpaCreateSession(context, kGpaContextSampleTypeDiscreteCounter, &session);
// The GpaSessionId is now supplied into GpaGetNumCounters() to get the number // of discrete counters that are available. GpaUInt32 num_counters = 0; GpaGetNumCounters(session, &num_counters); for (GpaUInt32 i = 0; i < num_counters; ++i) { const char* name = nullptr; GpaUInt32 index = 0; const char* description = nullptr; const char* group = nullptr; GpaDataType data_type = kGpaDataTypeLast; GpaUsageType usage_type = kGpaUsageTypeList; GpaUuid uuid = {}; GpaCounterSampleType sample_type = kGpaCounterSampleTypeDiscrete;
// These next set of counter querying entrypoints now take in a GpaSessionId // rather than the GpaContextId. GpaGetCounterName(session, i, &name); GpaGetCounterIndex(session, name, &index); assert(i == index); GpaGetCounterDescription(session, i, &description); GpaGetCounterDataType(session, i, &data_type); GpaGetCounterUsageType(session, i, &usage_type); GpaGetCounterUuid(session, i, &uuid); GpaGetCounterSampleType(session, i, &sample_type); assert(sample_type == kGpaCounterSampleTypeDiscrete); } GpaUInt32 desired_counter_index = 0; GpaEnableCounter(session, desired_counter_index); GpaBeginSession(session); ...}加载 GPUPerfAPI 库
GPUPerfAPI 二进制发行版包含每个支持 API 的独立库文件。下表显示了每个 API 的库文件名
| API | 库文件名 |
|---|---|
| Vulkan | 64 位 Windows:GPUPerfAPIVK-x64.dll |
64 位 Linux:libGPUPerfAPIVK.so | | DirectX 12 | 64 位 Windows:GPUPerfAPIDX12-x64.dll | | DirectX 11 | 64 位 Windows:GPUPerfAPIDX11-x64.dll | | OpenGL | 64 位 Windows:GPUPerfAPIGL-x64.dll
64 位 Linux:libGPUPerfAPIGL.so |
使用 GPUPerfAPI 库
-
包含头文件 gpu_performance_api/gpu_perf_api.h。对于 Vulkan,包含 gpu_performance_api/gpu_perf_api_vk.h。
-
声明一个 GpaGetFuncTablePtrType 类型的变量
-
加载 GPUPerfAPI 库
-
在 Windows 上,对您选择的 API 的 GPUPerfAPI DLL 使用
LoadLibrary(请参阅上表) -
在 Linux 上,对您选择的 API 的 GPUPerfAPI 共享库使用
dlopen(请参阅上表)
-
-
获取
GpaGetFuncTable函数的地址-
在 Windows 上,使用
GetProcAddres -
在 Linux 上,使用
dlsym
-
-
调用 GpaGetFuncTable 以获取每个 API 的函数指针表。
上述所有操作都可以使用 gpu_perf_api_interface_loader.h C++ 头文件进行简化。此头文件简化了 GPA 入口点的加载和初始化。以下代码显示了如何使用此头文件加载和初始化 GPA 的 DirectX 12 版本
#include "gpu_performance_api/gpu_perf_api_interface_loader.h"
#ifdef __cplusplusGpaApiManager* GpaApiManager::gpa_api_manager_ = nullptr;#endifGpaFuncTableInfo* gpa_function_table_info = nullptr;GpaFunctionTable* gpa_function_table = nullptr;
bool InitializeGpa(){ bool ret_val = false;
if (kGpaStatusOk == GpaApiManager::Instance()->LoadApi(kGpaApiDirectx12)) { gpa_function_table = GpaApiManager::Instance()->GetFunctionTable(kGpaApiDirectx12);
if (nullptr != gpa_function_table) { ret_val = kGpaStatusOk == gpa_function_table->GpaInitialize(kGpaInitializeDefaultBit); } }
return ret_val;}注册日志回调
提供了一个用于注册回调函数的入口点,GPUPerfAPI 将使用该回调函数来报告有关错误和通用 API 用法的其他信息。建议所有 GPUPerfAPI 客户端至少注册一个用于错误消息的日志记录回调。每当 GPUPerfAPI 函数返回错误时,它都会输出一条日志消息,其中包含有关导致错误的条件的更多信息。
要使用此功能,您必须定义一个具有以下签名的静态函数
void MyLoggingFunction(GpaLoggingType message_type, const char* message)使用 GpaRegisterLoggingCallback 入口点注册该函数。
注册的函数将接收注册的消息类型的回调。消息类型会传递到日志记录函数中,以便可以根据需要以不同的方式处理不同的消息类型。例如,错误可以输出到 stderr 或用于引发断言,而消息和跟踪信息可以输出到应用程序或工具的正常日志文件中。工具可能还希望在将消息写入之前,在日志消息前加上日志类型的字符串表示。传递到日志记录函数的这些消息末尾不会自动加上换行符,从而允许更灵活地处理消息。
初始化和销毁 GPUPerfAPI 实例
必须在创建渲染上下文或设备之前初始化 GPUPerfAPI,以便驱动程序可以为访问硬件数据做好准备。对于 DirectX 12 或 Vulkan,必须在创建队列之前完成初始化。使用完 GPUPerfAPI 后,应销毁 GPUPerfAPI 实例。对于 DirectX 12,必须在销毁设备之前完成销毁。
可以使用以下方法初始化和销毁 GPUPerfAPI
| GPA 初始化/销毁方法 | 简要说明 |
|---|---|
| GpaInitialize | 初始化驱动程序,以便公开计数器。 |
| GpaDestroy | 撤销任何初始化,以确保在未进行配置文件分析的应用程序中行为正确。 |
初始化 GPUPerfAPI 实例的代码示例可以在上面的 GpaInterfaceLoader 示例代码 中看到
打开和关闭上下文
在初始化 GPUPerfAPI 实例并创建必要的 API 特定构造之后,可以使用 GpaOpenContext 函数打开一个上下文。一旦上下文打开,您就可以查询有关硬件设备的信息,包括支持的样本类型,以及创建和开始一个会话。使用完 GPUPerfAPI 后,应关闭上下文。
可以使用以下方法打开和关闭上下文
| 上下文处理方法 | 简要说明 |
|---|---|
| GpaOpenContext | 打开指定上下文中的计数器以供读取。 |
| GpaCloseContext | 关闭指定上下文中的计数器。 |
调用 GpaOpenContext 时,所提供 context 的类型取决于所使用的 API。请参阅下表了解应传递给 GpaOpenContext 的必需类型
| API | GpaOpenContext context 参数类型 |
|---|---|
| Vulkan | GpaVkContextOpenInfo* |
(在 gpu_perf_api_vk.h 中定义) | | DirectX 12 | ID3D12Device* | | DirectX 11 | ID3D11Device* | | OpenGL | Windows:HGLRC
Linux:GLXContext |
查询上下文和样本类型
创建上下文后,您可以使用返回的 GpaContextId 来查询有关硬件和可用性能计数器样本类型的信息。
可以使用以下方法查询有关上下文的信息
| 上下文查询方法 | 简要说明 |
|---|---|
| GpaGetSupportedSampleTypes | 获取指定上下文支持的样本类型的掩码。 |
| GpaGetDeviceAndRevisionId | 获取与指定上下文关联的 GPU 设备和修订 ID。 |
| GpaGetDeviceName | 获取与指定上下文关联的 GPU 的设备名称。 |
| GpaGetDeviceGeneration | 获取与指定上下文关联的 GPU 的设备代系。 |
| GpaGetDeviceMaxWaveSlots | 获取与指定上下文关联的 GPU 的最大波形槽数。 |
创建和使用会话
创建上下文后,可以创建一个会话。会话特定于一种性能计数器样本类型,公开可用计数器,并且还是启用计数器、对 GPU 工作负载进行采样以及存储/检索结果的容器。
可以使用以下方法来管理会话
| 会话处理方法 | 简要说明 |
|---|---|
| GpaCreateSession | 创建会话。 |
| GpaDeleteSession | 删除会话对象。 |
| GpaBeginSession | 开始对当前已启用计数器集进行采样。 |
| GpaEndSession | 结束对当前已启用计数器集进行采样。 |
可以使用以下方法来查询性能计数器信息
| 计数器查询方法 | 简要说明 |
|---|---|
| GpaGetNumCounters | 获取可用计数器的数量。 |
| GpaGetCounterName | 获取指定计数器的名称。 |
| GpaGetCounterIndex | 根据名称获取计数器的索引(不区分大小写)。 |
| GpaGetCounterGroup | 获取指定计数器的组。 |
| GpaGetCounterDescription | 获取指定计数器的描述。 |
| GpaGetCounterDataType | 获取指定计数器的数据类型。 |
| GpaGetCounterUsageType | 获取指定计数器的用法类型。 |
| GpaGetCounterUuid | 获取指定计数器的 UUID。 |
| GpaGetCounterSampleType | 获取指定计数器的支持的样本类型。 |
| GpaGetDataTypeAsStr | 获取指定计数器数据类型的字符串名称。 |
| GpaGetUsageTypeAsStr | 获取指定计数器用法类型的字符串名称。 |
在会话上启用计数器
在创建会话但尚未在该会话上进行采样之前,应启用计数器。这必须在调用 GpaCreateSession 之后,但在调用 GpaBeginSession 之前完成。
可以使用以下方法来启用/禁用会话上的计数器
| 计数器启用/禁用方法 | 简要说明 |
|---|---|
| GpaEnableCounter | 启用指定计数器。 |
| GpaDisableCounter | 禁用指定计数器。 |
| GpaEnableCounterByName | 使用计数器名称(不区分大小写)启用指定计数器。 |
| GpaDisableCounterByName | 使用计数器名称(不区分大小写)禁用指定计数器。 |
| GpaEnableAllCounters | 启用所有计数器。 |
| GpaDisableAllCounters | 禁用所有计数器。 |
查询已启用的计数器和计数器调度
还可以查询会话以获取有关哪些计数器已启用以及当前已启用计数器集所需通过数的有关信息。
可以使用以下方法来查询会话上的已启用计数器和计数器调度
| 计数器调度查询方法 | 简要说明 |
|---|---|
| GpaGetPassCount | 获取当前已启用计数器集所需的通过数。 |
| GpaGetNumEnabledCounters | 获取已启用计数器的数量。 |
| GpaGetEnabledIndex | 获取已启用计数器的计数器索引。 |
| GpaIsCounterEnabled | 检查计数器是否已启用。 |
创建和管理样本
在会话上启用计数器并启动会话后,可以创建 GPA 命令列表和样本。样本是收集性能计数器的 GPU 工作负载。每个样本都将收集所有已启用的计数器。对于 DirectX 12 和 Vulkan,样本可以从一个命令列表开始,并在另一个命令列表结束。对于 DirectX 12 bundles 和 Vulkan secondary command buffers,还需要特殊处理。
可以使用以下方法在会话上创建和管理样本
| 样本处理方法 | 简要说明 |
|---|---|
| GpaBeginCommandList | 开始用于采样的命令列表。 |
| GpaEndCommandList | 结束用于采样的命令列表。 |
| GpaBeginSample | 在命令列表中开始一个样本。 |
| GpaEndSample | 在命令列表中结束一个样本。 |
| GpaContinueSampleOnCommandList | 在另一个主命令列表中继续一个主命令列表样本。 |
| GpaCopySecondarySamples | 将一组样本从辅助命令列表复制回执行该辅助命令列表的主命令列表。 |
| GpaGetSampleCount | 返回为指定会话创建的样本数。 |
查询结果
采样完成后且会话结束后,就可以读取样本结果。对于 DirectX 12 和 Vulkan,包含样本的命令列表或命令缓冲区必须已完全执行,然后才能获得结果。
可以使用以下方法来检查结果是否可用并读取样本结果
| 结果查询方法 | 简要说明 |
|---|---|
| GpaIsPassComplete | 检查通过是否已完成。 |
| GpaIsSessionComplete | 检查会话中所有样本的结果是否都可用。 |
| GpaGetSampleResultSize | 获取给定样本的结果大小。 |
| GpaGetSampleResult | 获取给定样本的结果数据。 |
显示状态/错误
所有 GPUPerfAPI 函数都返回一个 GpaStatus 代码来指示成功或失败。可以使用以下方法检索状态或错误代码的简单字符串表示
| 状态/错误助手方法 | 简要说明 |
|---|---|
| GpaGetStatusAsStr | 获取 GpaStatus 值的字符串表示。 |
多遍计数器收集
收集一些单独的计数器和一些计数器的组合将需要多次传递。在启用计数器后,您可以查询所需的通过数。如果通过数大于一,您需要为每次传递执行相同的 GPU 工作负载一次。对于 DirectX 12 和 Vulkan,这通常意味着需要多次录制相同的命令列表或命令缓冲区,为每次传递调用 GpaBeginCommandList,并在命令列表中为相同的工作负载开始和结束样本。对于其他图形和计算 API,这意味着多次以相同的顺序执行相同的绘制调用或调度相同的内核。必须在每次传递中找到相同的样本 ID,并且该样本 ID 必须用于每次传递中的相同工作负载。如果无法做到或不方便重复要进行配置文件分析的操作,请选择一个只需要一次传递的计数器集。对于需要多次传递的计数器集,结果在所有传递完成后才可用。
Vulkan 的特定用法说明
为了在 Vulkan 驱动程序中启用计数器收集,需要几个 Vulkan 扩展。使用 GPUPerfAPI 进行配置文件分析的应用程序需要在 Vulkan 实例和设备初始化过程中请求这些扩展。GPUPerfAPI 通过在 gpu_performance_api/gpu_perf_api_vk.h 头文件中定义三个宏来简化此过程:AMD_GPA_REQUIRED_INSTANCE_EXTENSION_NAME_LIST 用于必需的实例扩展,AMD_GPA_REQUIRED_DEVICE_EXTENSION_NAME_LIST 用于必需的设备扩展,以及 AMD_GPA_OPTIONAL_DEVICE_EXTENSION_NAME_LIST 用于可选但推荐的设备扩展。在 AMD_GPA_REQUIRED_INSTANCE_EXTENSION_NAME_LIST 中定义的扩展应包含在传递给 vkCreateInstance 函数的 VkInstanceCreateInfo 结构中。类似地,在 AMD_GPA_REQUIRED_DEVICE_EXTENSION_NAME_LIST 和 AMD_GPA_OPTIONAL_DEVICE_EXTENSION_NAME_LIST 中定义的扩展应包含在传递给 VkCreateDevice 函数的 VkDeviceCreateInfo 结构中。
Bundles (DirectX 12) 和 Secondary Command Buffers (Vulkan) 的特定用法说明
虽然 GPUPerfAPI 支持 Bundles 或 Secondary Command Buffers(在此均称为“辅助命令列表”)中的样本,但它们需要特殊处理。主命令列表和辅助命令列表都必须使用 GpaBeginCommandList 启动。可以在两种类型的命令列表上创建样本;但是,必须将辅助命令列表上的样本复制回主命令列表。这是通过 GpaCopySecondarySamples 函数完成的。将样本复制回主命令列表后,在主命令列表执行完成后即可获得结果。Bundles 或 Secondary Command Buffers 必须为每次计数器传递重新录制。这也意味着必须创建额外的 GpaCommandListId 实例(每个 Bundle 或 Secondary Command Buffer 的每次传递一个),以便在执行后支持从 Bundles 或 Secondary Command Buffers 复制结果。
在不同命令列表上开始和结束的样本的特定用法说明
对于 DirectX 12 和 Vulkan,GPUPerfAPI 支持在一个命令列表中开始一个样本并在另一个命令列表中结束它。要使其正常工作,应用程序必须按正确的顺序执行命令列表——结束样本的命令列表必须在开始样本的命令列表之后执行。开始样本的命令列表和结束样本的命令列表都必须使用 GpaBeginCommandList 启动。在第一个命令列表中使用 GpaBeginSample 开始样本后,可以通过调用 GpaContinueSampleOnCommandList 在另一个命令列表中继续它。继续之后,可以使用 GpaEndSample 并指定第二个命令列表来结束样本。
部署 GPUPerfAPI
要部署使用 GPUPerfAPI 的应用程序,只需确保必要的 GPUPerfAPI 库可用,并且可以使用主机操作系统的正常库搜索机制(即 Windows 上的 PATH 和 Linux 上的 LD_LIBRARY_PATH)对其进行加载。
在 Windows 上部署 DirectX 11 版本时,如果需要支持具有多个 AMD GPU 的系统,您还必须部署 GPUPerfAPIDXGetAMDDeviceInfo-x64.dll。此库由 GPA 用于在运行时确定正在使用哪个 GPU 进行渲染。对于单 GPU 系统,则不需要此库。