计时(Direct3D 12 图形)

本节介绍如何查询时间戳,以及如何校准 GPU 和 CPU 时间戳计数器。

时间戳频率

应用程序可以按命令队列查询 GPU 时间戳频率, (引用 ID3D12CommandQueue::GetTimestampFrequency 方法) 。

返回的频率以 Hz(时钟周期/秒)为单位。 如果指定的命令队列不支持时间戳 (查看 查询 部分) 中的表,则此 API (失败,并返回 E_FAIL) 。 D3D12_COMMAND_LIST_TYPE_DIRECTD3D12_COMMAND_LIST_TYPE_COMPUTE 始终支持时间戳。 如果 D3D12_FEATURE_DATA_D3D12_OPTIONS3::CopyQueueTimestampQueriesSupported 成员为 TRUE,D3D12_COMMAND_LIST_TYPE_COPY可以选择支持时间戳。

时间戳校准

D3D12 使应用程序能够将从时间戳查询获得的结果与从调用 QueryPerformanceCounter 获得的结果相关联。 这是通过调用 ID3D12CommandQueue::GetClockCalibration 实现的

当 GPU 完成上述所有工作负载时,GPU 将采样时间戳。 这是 Direct3D 11 采用的相同行为, (请参阅 GitHub ) 上的 Direct3D 11.3 功能规范中的D3D11_QUERY_TIMESTAMP。 这意味着时间戳查询是 Direct3D 12 中 (BOP) 操作。

GetClockCalibration 对给定命令队列的 GPU 时间戳计数器进行采样,并通过 QueryPerformanceCounter 对 CPU 计数器进行采样,这两项操作几乎同时进行。 如果指定的命令队列不支持时间戳, (返回E_FAIL) 此 API 会再次失败, (查看 查询 主题) 中的表。

请注意,GPU 和 CPU 时间戳计数器不一定与这些处理器的时钟速度直接相关,而是从时间戳时钟周期开始工作。

时间戳查询

可以在命令列表 (获取时间戳,而不是通过时间戳查询) 命令队列上的 CPU 端调用。 (有关常规 ) 查询的详细信息,请参阅查询。

所有时间戳查询对实际查询使用 类型D3D12_QUERY_TYPE_TIMESTAMP 。 但是,由于硬件限制, D3D12_COMMAND_LIST_TYPE_DIRECTD3D12_COMMAND_LIST_TYPE_COMPUTE 使用的 D3D12_QUERY_HEAP_TYPED3D12_COMMAND_LIST_TYPE_COPY 使用的D3D12_QUERY_HEAP_TYPE不同。

直接队列和计算队列使用 D3D12_QUERY_HEAP_TYPE_TIMESTAMP

复制队列使用 D3D12_QUERY_HEAP_TYPE_COPY_QUEUE_TIMESTAMP

仅当 D3D12_FEATURE_DATA_D3D12_OPTIONS3::CopyQueueTimestampQueriesSupported 成员为 TRUE 时,才支持复制队列查询。

时间戳查询通过 ID3D12GraphicsCommandList::ResolveQueryData 解析后,是一个表示时钟周期的 UINT64ID3D12CommandQueue::GetClockCalibration 返回,因此必须将其除以队列频率来获取长度(以秒为单位)。

重要

为提高准确性,在计算第二或毫秒的时间戳间隔时,请使用浮点算术。 例如,请使用 queriedTicks / (double)Frequency 而不是 queriedTicks / Frequency

计数器和查询

ID3D12Device::SetStablePowerState

ID3D12Object::SetName

ID3DUserDefinedAnnotation

性能度量