cancel
Showing results for 
Search instead for 
Did you mean: 

Archives Discussions

silverlan
Adept I

Vulkan - Timestamp query never becomes available

There seems to be a problem with timestamp queries when using more than one query at a time. I've attached a sample-program to this discussion. It's an adaptation of the cube demo from the Vulkan SDK, I've marked all of my changes in the code with "/* TIMESTAMP QUERY */". What I've changed is:

1) Creating a new query pool with a query count of 2 in demo_create_device

2) Reset and write both queries in demo_draw_build_cmd

3) Retrieve the query results in demo_draw

It's supposed to print "Result 1 available" and "Result 2 available" for each query when they become available.

This works fine on NVIDIA hardware, both results are available immediately. However, on AMD hardware, only query result #2 becomes available and query result #1 stays unavailable indefinitely.

I've tested this on 2 different NVIDIA systems, and 2 AMD systems with consistent outcomes.

I've also noticed that if query #2 is not reset, both results become available. This doesn't make sense, since resetting query #2 should have no effect on query #1 (And a query has to be reset before being written to, according to the specification). Here's a video of what I mean: bandicam 2016 05 19 18 24 38 716 - YouTube

I've also noticed that if only 1 query is being created, and everything else stays the same, the result does become available just fine. The problem only occurs if more than 1 query is created.

I have the latest Vulkan beta drivers (Version 16.15.2401.1001 Public Vulkan Beta), my card is a Radeon R9 280, and I'm on Windows 10 x64.

0 Likes
1 Solution

There's a couple of things that caught my attention in the source code you provided:

* In l. 683 & 685: vkCmdWriteTimestamp() calls pass VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT through the <pipelineStage> argument. This should be set to VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT instead, assuming your goal here is to ensure the timestamp gets written after all enqueued commands finish executing.
* ln. 801 & l. 812: <dataSize> argument value, as passed through the vkGetQueryPoolResults() call, is set to sizeof(uint32) * 2, which indicates your app is expecting each timestamp to be 64-bit. If that's true, then you should also set the VK_QUERY_RESULT_64_BIT bit in the <flags> argument.
* ln. 801 & l. 812: VK_QUERY_RESULT_WITH_AVAILABILITY_BIT your app passes in the same call lets vkGetQueryPoolResults() leave before the results become available. Hence, it is not true that both timestamps are guaranteed to be reported as available the moment each of these calls returns. For that to happen, you also need to set the VK_QUERY_RESULT_WAIT_BIT bit for the <flags> argument. This will cause the call to block until the timestamp values become available.

Having said that, I can confirm there is a bug in our implementation of vkCmdResetQueryPool(), which causes the <firstQuery> argument value to be assumed to be always 0. In case of your app, this exhibits as a lock-up, because the second "reset query pool" instruction resets both query slots, instead of only the second one. We are going to fix this for the next driver release, or the one that is going to follow. For now, as a workaround, please reset both slots at once.

Thank you for reporting this issue!

View solution in original post

2 Replies
dwitczak
Staff

This question has somehow slipped through unnoticed, apologies. Will have a look at this later today and be back with you shortly.

0 Likes

There's a couple of things that caught my attention in the source code you provided:

* In l. 683 & 685: vkCmdWriteTimestamp() calls pass VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT through the <pipelineStage> argument. This should be set to VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT instead, assuming your goal here is to ensure the timestamp gets written after all enqueued commands finish executing.
* ln. 801 & l. 812: <dataSize> argument value, as passed through the vkGetQueryPoolResults() call, is set to sizeof(uint32) * 2, which indicates your app is expecting each timestamp to be 64-bit. If that's true, then you should also set the VK_QUERY_RESULT_64_BIT bit in the <flags> argument.
* ln. 801 & l. 812: VK_QUERY_RESULT_WITH_AVAILABILITY_BIT your app passes in the same call lets vkGetQueryPoolResults() leave before the results become available. Hence, it is not true that both timestamps are guaranteed to be reported as available the moment each of these calls returns. For that to happen, you also need to set the VK_QUERY_RESULT_WAIT_BIT bit for the <flags> argument. This will cause the call to block until the timestamp values become available.

Having said that, I can confirm there is a bug in our implementation of vkCmdResetQueryPool(), which causes the <firstQuery> argument value to be assumed to be always 0. In case of your app, this exhibits as a lock-up, because the second "reset query pool" instruction resets both query slots, instead of only the second one. We are going to fix this for the next driver release, or the one that is going to follow. For now, as a workaround, please reset both slots at once.

Thank you for reporting this issue!