gfx
gfx copied to clipboard
Putting in place plumbing to expose timestamp query related details. Is timestamp querying supported by the device? What is the tick period?
Problem
Currently, gfx-hal
exposes a way to generate timestamp queries, there is no way to check whether timestamp queries are supported by the device, or get the period of the ticks returned by the query.
Getting this information
Using Vulkan: this information is stored within the VkPhysicalDeviceLimits
info structure. See timestampComputeAndGraphics
and timestampPeriod
fields.
Using DX12: this information is obtained by calling ID3D12CommandQueue::GetTimestampFrequency method
, which is a method on ID3D12CommandQueue
. If the HRESULT of the get is an error, then the device?/command queue? does not support timestamp querying.
Note that an ID3D12CommandQueue
is created by calling the ID3D12Device::CreateCommandQueue
method on ID3D12Device
.
Using DX11/Metal/OpenGL: I don't know what the situation is for these backends, so I hope others can provide information.
Solution
First, let us examine the Vulkan case.
Vulkan. In my understanding, a PhysicalDevice
is publicly accessible as a field on an Adapter
object. PhysicalDevice
has the properties
field of type vk::PhysicalDeviceProperties
, which in turn has a field called limits
containing the information we need to expose.
Therefore, we need a method on PhysicalDevice
which returns the relevant information stored in its properties
field. Suppose we call this method get_timestamp_query_info
, for the purposes of the discussion (actual name left up to discussion). The PhysicalDevice
trait should specify such a method.
DX12. To implement get_timestamp_query_info
for DX12, one runs into an issue because unlike in the Vulkan case where the info is associated with a physical device, it seems that in the DX12 case, this information is associated with a logical device, ID3D12Device
, which can be obtained by calling the as_raw
method implemented for a (logical) Device
by the DX12 backend.
This means that we have to call adapter.physical_device.open
to get Gpu
object which stores a logical device, and then the get_timestamp_query
should be called on this device. This suggests that the gfx-hal trait which should specify the get_timestamp_query
method is Device
, and not PhysicalDevice
as we concluded when examining the Vulkan case. However, I think we would prefer to keep with what the Vulkan case demands.
In order to keep with the Vulkan case, maybe the DX12 impl of get_timestamp_query
for PhysicalDevice
should create a raw logical device much like what is done in the impl for open
. However, the this logical device is temporary, and only used to create a raw command queue, which can be called to get timestamp information, which is then returned to the user.
Conclusion
Can the gfx-hal API designers discuss what is the best way to approach the above problem? I will be happy to implement their recommended solution for the Vulkan and DX12 backends, but will have to leave the implementation for other backends to someone else.
Thanks for filing such a detailed issue!
First observation: we need to get that info when there is only a physical device available, just like Vulkan does. Otherwise, piping gfx-portability will be difficult.
Second observation: D3D12 has to create a logical device when enumerating adapters, so it's already available to us. The only thing we need extra is the queue. One of the ways to proceed would be having enumerate_adapters
to create queues for each adapter on D3D12 and querying the timestamp resolution.
Now, you also suggested to make the query a function. I really like this idea for making the cost of query optional, while still allowing gfx-portability to gather all the data. I think it's a good direction to take, possibly with other exposed limits and capabilities as well.
Your suggestions make sense to me :)
PR is in progress.
@msiglreith why are the timing related queries specific to command queues in DX12? Can the time period for a measured tick be different based on the queue's properties (priority, type, etc.)?
hmm, I guess queue type is the only interesting property. I suggest to just check for direct and compute and take the value. In the best case, all queues report the same property (hopefully). Worst case, compute or copy differ. Then we can also just say that these queues don't support timestamp queries for vk portability.