Timing (Direct3D 12 Graphics)
This section covers querying timestamps, and calibrating the GPU and CPU timestamp counters.
Timestamp frequency
Your application can query the GPU timestamp frequency on a per-command queue basis (refer to the ID3D12CommandQueue::GetTimestampFrequency method).
The returned frequency is measured in Hz (ticks/sec). If the specified command queue doesn't support timestamps (see the table in the Queries section), then this API fails (and returns E_FAIL). D3D12_COMMAND_LIST_TYPE_DIRECT and D3D12_COMMAND_LIST_TYPE_COMPUTE always support timestamps. D3D12_COMMAND_LIST_TYPE_COPY optionally supports timestamps if the D3D12_FEATURE_DATA_D3D12_OPTIONS3::CopyQueueTimestampQueriesSupported member is TRUE.
Timestamp calibration
D3D12 enables applications to correlate results obtained from timestamp queries with results obtained from calling QueryPerformanceCounter
. This is enabled by the call ID3D12CommandQueue::GetClockCalibration.
A timestamp is sampled by the GPU at the moment that the GPU is finished with all of the preceding workload. It's the same behavior adopted by Direct3D 11 (see D3D11_QUERY_TIMESTAMP in the Direct3D 11.3 Functional Specification on GitHub). That means that timestamp queries are a bottom-of-pipe (BOP) operation in Direct3D 12.
GetClockCalibration samples the GPU timestamp counter for a given command queue and samples the CPU counter via QueryPerformanceCounter
at nearly the same time. Again this API fails (returning E_FAIL) if the specified command queue does not support timestamps (see the table in the Queries topic).
Note that GPU and CPU timestamp counters are not necessarily directly related to the clock speed of these processors, but instead work from timestamp ticks.
Timestamp queries
You can obtain timestamps as part of a command list (rather than a CPU-side call on a command queue) via timestamp queries. (See Queries for more information about queries in general).
All timestamp queries use the type D3D12_QUERY_TYPE_TIMESTAMP for the actual query. However, due to hardware limitations, D3D12_COMMAND_LIST_TYPE_DIRECT and D3D12_COMMAND_LIST_TYPE_COMPUTE use a different D3D12_QUERY_HEAP_TYPE from the one that D3D12_COMMAND_LIST_TYPE_COPY uses.
Direct and compute queues use D3D12_QUERY_HEAP_TYPE_TIMESTAMP.
Copy queues use D3D12_QUERY_HEAP_TYPE_COPY_QUEUE_TIMESTAMP.
Copy queue queries are supported only if the D3D12_FEATURE_DATA_D3D12_OPTIONS3::CopyQueueTimestampQueriesSupported member is TRUE.
Timestamp queries, once resolved via ID3D12GraphicsCommandList::ResolveQueryData, are a UINT64 that represents ticks, as is returned by ID3D12CommandQueue::GetClockCalibration, and as such it must be divided by the queue frequency to get the length in seconds.
Important
For accuracy, use floating-point arithmetic when calculating second or millisecond intervals of timestamps. For example, use queriedTicks / (double)Frequency
instead of queriedTicks / Frequency
.