Vulkan Logo

17. Queries

Queries provide a mechanism to return information about the processing of a sequence of Vulkan commands. Query operations are asynchronous, and as such, their results are not returned immediately. Instead, their results, and their availability status are stored in a Query Pool. The state of these queries can be read back on the host, or copied to a buffer object on the device.

The supported query types are Occlusion Queries, Pipeline Statistics Queries, and Timestamp Queries.

17.1. Query Pools

Queries are managed using query pool objects. Each query pool is a collection of a specific number of queries of a particular type.

Query pools are represented by VkQueryPool handles:

// Provided by VK_VERSION_1_0
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkQueryPool)

To create a query pool, call:

// Provided by VK_VERSION_1_0
VkResult vkCreateQueryPool(
    VkDevice                                    device,
    const VkQueryPoolCreateInfo*                pCreateInfo,
    const VkAllocationCallbacks*                pAllocator,
    VkQueryPool*                                pQueryPool);
  • device is the logical device that creates the query pool.

  • pCreateInfo is a pointer to a VkQueryPoolCreateInfo structure containing the number and type of queries to be managed by the pool.

  • pAllocator controls host memory allocation as described in the Memory Allocation chapter.

  • pQueryPool is a pointer to a VkQueryPool handle in which the resulting query pool object is returned.

Valid Usage (Implicit)
  • VUID-vkCreateQueryPool-device-parameter
    device must be a valid VkDevice handle

  • VUID-vkCreateQueryPool-pCreateInfo-parameter
    pCreateInfo must be a valid pointer to a valid VkQueryPoolCreateInfo structure

  • VUID-vkCreateQueryPool-pAllocator-parameter
    If pAllocator is not NULL, pAllocator must be a valid pointer to a valid VkAllocationCallbacks structure

  • VUID-vkCreateQueryPool-pQueryPool-parameter
    pQueryPool must be a valid pointer to a VkQueryPool handle

Return Codes
Success
  • VK_SUCCESS

Failure
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

The VkQueryPoolCreateInfo structure is defined as:

// Provided by VK_VERSION_1_0
typedef struct VkQueryPoolCreateInfo {
    VkStructureType                  sType;
    const void*                      pNext;
    VkQueryPoolCreateFlags           flags;
    VkQueryType                      queryType;
    uint32_t                         queryCount;
    VkQueryPipelineStatisticFlags    pipelineStatistics;
} VkQueryPoolCreateInfo;
  • sType is a VkStructureType value identifying this structure.

  • pNext is NULL or a pointer to a structure extending this structure.

  • flags is reserved for future use.

  • queryType is a VkQueryType value specifying the type of queries managed by the pool.

  • queryCount is the number of queries managed by the pool.

  • pipelineStatistics is a bitmask of VkQueryPipelineStatisticFlagBits specifying which counters will be returned in queries on the new pool, as described below in Pipeline Statistics Queries.

pipelineStatistics is ignored if queryType is not VK_QUERY_TYPE_PIPELINE_STATISTICS.

Valid Usage
  • VUID-VkQueryPoolCreateInfo-queryType-00791
    If the pipelineStatisticsQuery feature is not enabled, queryType must not be VK_QUERY_TYPE_PIPELINE_STATISTICS

  • VUID-VkQueryPoolCreateInfo-queryType-00792
    If queryType is VK_QUERY_TYPE_PIPELINE_STATISTICS, pipelineStatistics must be a valid combination of VkQueryPipelineStatisticFlagBits values

  • VUID-VkQueryPoolCreateInfo-queryType-09534
    If queryType is VK_QUERY_TYPE_PIPELINE_STATISTICS, pipelineStatistics must not be zero

  • VUID-VkQueryPoolCreateInfo-queryCount-02763
    queryCount must be greater than 0

Valid Usage (Implicit)
  • VUID-VkQueryPoolCreateInfo-sType-sType
    sType must be VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO

  • VUID-VkQueryPoolCreateInfo-pNext-pNext
    pNext must be NULL

  • VUID-VkQueryPoolCreateInfo-flags-zerobitmask
    flags must be 0

  • VUID-VkQueryPoolCreateInfo-queryType-parameter
    queryType must be a valid VkQueryType value

// Provided by VK_VERSION_1_0
typedef VkFlags VkQueryPoolCreateFlags;

VkQueryPoolCreateFlags is a bitmask type for setting a mask, but is currently reserved for future use.

To destroy a query pool, call:

// Provided by VK_VERSION_1_0
void vkDestroyQueryPool(
    VkDevice                                    device,
    VkQueryPool                                 queryPool,
    const VkAllocationCallbacks*                pAllocator);
  • device is the logical device that destroys the query pool.

  • queryPool is the query pool to destroy.

  • pAllocator controls host memory allocation as described in the Memory Allocation chapter.

Valid Usage
  • VUID-vkDestroyQueryPool-queryPool-00793
    All submitted commands that refer to queryPool must have completed execution

  • VUID-vkDestroyQueryPool-queryPool-00794
    If VkAllocationCallbacks were provided when queryPool was created, a compatible set of callbacks must be provided here

  • VUID-vkDestroyQueryPool-queryPool-00795
    If no VkAllocationCallbacks were provided when queryPool was created, pAllocator must be NULL

Note

Applications can verify that queryPool can be destroyed by checking that vkGetQueryPoolResults() without the VK_QUERY_RESULT_PARTIAL_BIT flag returns VK_SUCCESS for all queries that are used in command buffers submitted for execution.

Valid Usage (Implicit)
  • VUID-vkDestroyQueryPool-device-parameter
    device must be a valid VkDevice handle

  • VUID-vkDestroyQueryPool-queryPool-parameter
    If queryPool is not VK_NULL_HANDLE, queryPool must be a valid VkQueryPool handle

  • VUID-vkDestroyQueryPool-pAllocator-parameter
    If pAllocator is not NULL, pAllocator must be a valid pointer to a valid VkAllocationCallbacks structure

  • VUID-vkDestroyQueryPool-queryPool-parent
    If queryPool is a valid handle, it must have been created, allocated, or retrieved from device

Host Synchronization
  • Host access to queryPool must be externally synchronized

Possible values of VkQueryPoolCreateInfo::queryType, specifying the type of queries managed by the pool, are:

// Provided by VK_VERSION_1_0
typedef enum VkQueryType {
    VK_QUERY_TYPE_OCCLUSION = 0,
    VK_QUERY_TYPE_PIPELINE_STATISTICS = 1,
    VK_QUERY_TYPE_TIMESTAMP = 2,
} VkQueryType;

17.2. Query Operation

In order for a VkCommandBuffer to record query management commands, the queue family for which its VkCommandPool was created must support the appropriate type of operations (graphics, compute) suitable for the query type of a given query pool.

Each query in a query pool has a status that is either unavailable or available, and also has state to store the numerical results of a query operation of the type requested when the query pool was created. Resetting a query via vkCmdResetQueryPool or vkResetQueryPool sets the status to unavailable and makes the numerical results undefined. A query is made available by the operation of vkCmdEndQuery, vkCmdWriteTimestamp2, or vkCmdWriteTimestamp. Both the availability status and numerical results can be retrieved by calling either vkGetQueryPoolResults or vkCmdCopyQueryPoolResults.

After query pool creation, each query is in an uninitialized state and must be reset before it is used. Queries must also be reset between uses.

If a logical device includes multiple physical devices, then each command that writes a query must execute on a single physical device, and any call to vkCmdBeginQuery must execute the corresponding vkCmdEndQuery command on the same physical device.

To reset a range of queries in a query pool on a queue, call:

// Provided by VK_VERSION_1_0
void vkCmdResetQueryPool(
    VkCommandBuffer                             commandBuffer,
    VkQueryPool                                 queryPool,
    uint32_t                                    firstQuery,
    uint32_t                                    queryCount);
  • commandBuffer is the command buffer into which this command will be recorded.

  • queryPool is the handle of the query pool managing the queries being reset.

  • firstQuery is the initial query index to reset.

  • queryCount is the number of queries to reset.

When executed on a queue, this command sets the status of query indices [firstQuery, firstQuery + queryCount - 1] to unavailable.

This command defines an execution dependency between other query commands that reference the same query.

The first synchronization scope includes all commands which reference the queries in queryPool indicated by firstQuery and queryCount that occur earlier in submission order.

The second synchronization scope includes all commands which reference the queries in queryPool indicated by firstQuery and queryCount that occur later in submission order.

The operation of this command happens after the first scope and happens before the second scope.

Valid Usage
  • VUID-vkCmdResetQueryPool-firstQuery-09436
    firstQuery must be less than the number of queries in queryPool

  • VUID-vkCmdResetQueryPool-firstQuery-09437
    The sum of firstQuery and queryCount must be less than or equal to the number of queries in queryPool

  • VUID-vkCmdResetQueryPool-None-02841
    All queries used by the command must not be active

Valid Usage (Implicit)
  • VUID-vkCmdResetQueryPool-commandBuffer-parameter
    commandBuffer must be a valid VkCommandBuffer handle

  • VUID-vkCmdResetQueryPool-queryPool-parameter
    queryPool must be a valid VkQueryPool handle

  • VUID-vkCmdResetQueryPool-commandBuffer-recording
    commandBuffer must be in the recording state

  • VUID-vkCmdResetQueryPool-commandBuffer-cmdpool
    The VkCommandPool that commandBuffer was allocated from must support graphics, or compute operations

  • VUID-vkCmdResetQueryPool-renderpass
    This command must only be called outside of a render pass instance

  • VUID-vkCmdResetQueryPool-commonparent
    Both of commandBuffer, and queryPool must have been created, allocated, or retrieved from the same VkDevice

Host Synchronization
  • Host access to commandBuffer must be externally synchronized

  • Host access to the VkCommandPool that commandBuffer was allocated from must be externally synchronized

Command Properties
Command Buffer Levels Render Pass Scope Supported Queue Types Command Type

Primary
Secondary

Outside

Graphics
Compute

Action

To reset a range of queries in a query pool on the host, call:

// Provided by VK_VERSION_1_2
void vkResetQueryPool(
    VkDevice                                    device,
    VkQueryPool                                 queryPool,
    uint32_t                                    firstQuery,
    uint32_t                                    queryCount);
  • device is the logical device that owns the query pool.

  • queryPool is the handle of the query pool managing the queries being reset.

  • firstQuery is the initial query index to reset.

  • queryCount is the number of queries to reset.

This command sets the status of query indices [firstQuery, firstQuery + queryCount - 1] to unavailable.

Valid Usage
  • VUID-vkResetQueryPool-firstQuery-09436
    firstQuery must be less than the number of queries in queryPool

  • VUID-vkResetQueryPool-firstQuery-09437
    The sum of firstQuery and queryCount must be less than or equal to the number of queries in queryPool

  • VUID-vkResetQueryPool-None-02665
    The hostQueryReset feature must be enabled

  • VUID-vkResetQueryPool-firstQuery-02741
    Submitted commands that refer to the range specified by firstQuery and queryCount in queryPool must have completed execution

  • VUID-vkResetQueryPool-firstQuery-02742
    The range of queries specified by firstQuery and queryCount in queryPool must not be in use by calls to vkGetQueryPoolResults or vkResetQueryPool in other threads

Valid Usage (Implicit)
  • VUID-vkResetQueryPool-device-parameter
    device must be a valid VkDevice handle

  • VUID-vkResetQueryPool-queryPool-parameter
    queryPool must be a valid VkQueryPool handle

  • VUID-vkResetQueryPool-queryPool-parent
    queryPool must have been created, allocated, or retrieved from device

Once queries are reset and ready for use, query commands can be issued to a command buffer. Occlusion queries and pipeline statistics queries count events - drawn samples and pipeline stage invocations, respectively - resulting from commands that are recorded between a vkCmdBeginQuery command and a vkCmdEndQuery command within a specified command buffer, effectively scoping a set of drawing and/or dispatching commands. Timestamp queries write timestamps to a query pool.

A query must begin and end in the same command buffer, although if it is a primary command buffer, and the inheritedQueries feature is enabled, it can execute secondary command buffers during the query operation. For a secondary command buffer to be executed while a query is active, it must set the occlusionQueryEnable, queryFlags, and/or pipelineStatistics members of VkCommandBufferInheritanceInfo to conservative values, as described in the Command Buffer Recording section. A query must either begin and end inside the same subpass of a render pass instance, or must both begin and end outside of a render pass instance (i.e. contain entire render pass instances).

If queries are used while executing a render pass instance that has multiview enabled, the query uses N consecutive query indices in the query pool (starting at query) where N is the number of bits set in the view mask in the subpass the query is used in. How the numerical results of the query are distributed among the queries is implementation-dependent. For example, some implementations may write each view’s results to a distinct query, while other implementations may write the total result to the first query and write zero to the other queries. However, the sum of the results in all the queries must accurately reflect the total result of the query summed over all views. Applications can sum the results from all the queries to compute the total result.

Queries used with multiview rendering must not span subpasses, i.e. they must begin and end in the same subpass.

To begin a query, call:

// Provided by VK_VERSION_1_0
void vkCmdBeginQuery(
    VkCommandBuffer                             commandBuffer,
    VkQueryPool                                 queryPool,
    uint32_t                                    query,
    VkQueryControlFlags                         flags);
  • commandBuffer is the command buffer into which this command will be recorded.

  • queryPool is the query pool that will manage the results of the query.

  • query is the query index within the query pool that will contain the results.

  • flags is a bitmask of VkQueryControlFlagBits specifying constraints on the types of queries that can be performed.

If the queryType of the pool is VK_QUERY_TYPE_OCCLUSION and flags contains VK_QUERY_CONTROL_PRECISE_BIT, an implementation must return a result that matches the actual number of samples passed. This is described in more detail in Occlusion Queries.

After beginning a query, that query is considered active within the command buffer it was called in until that same query is ended. Queries active in a primary command buffer when secondary command buffers are executed are considered active for those secondary command buffers.

This command defines an execution dependency between other query commands that reference the same query.

The first synchronization scope includes all commands which reference the queries in queryPool indicated by query that occur earlier in submission order.

The second synchronization scope includes all commands which reference the queries in queryPool indicated by query that occur later in submission order.

The operation of this command happens after the first scope and happens before the second scope.

Valid Usage
  • VUID-vkCmdBeginQuery-None-00807
    All queries used by the command must be unavailable

  • VUID-vkCmdBeginQuery-queryType-02804
    The queryType used to create queryPool must not be VK_QUERY_TYPE_TIMESTAMP

  • VUID-vkCmdBeginQuery-queryType-00800
    If the occlusionQueryPrecise feature is not enabled, or the queryType used to create queryPool was not VK_QUERY_TYPE_OCCLUSION, flags must not contain VK_QUERY_CONTROL_PRECISE_BIT

  • VUID-vkCmdBeginQuery-query-00802
    query must be less than the number of queries in queryPool

  • VUID-vkCmdBeginQuery-queryType-00803
    If the queryType used to create queryPool was VK_QUERY_TYPE_OCCLUSION, the VkCommandPool that commandBuffer was allocated from must support graphics operations

  • VUID-vkCmdBeginQuery-queryType-00804
    If the queryType used to create queryPool was VK_QUERY_TYPE_PIPELINE_STATISTICS and any of the pipelineStatistics indicate graphics operations, the VkCommandPool that commandBuffer was allocated from must support graphics operations

  • VUID-vkCmdBeginQuery-queryType-00805
    If the queryType used to create queryPool was VK_QUERY_TYPE_PIPELINE_STATISTICS and any of the pipelineStatistics indicate compute operations, the VkCommandPool that commandBuffer was allocated from must support compute operations

  • VUID-vkCmdBeginQuery-commandBuffer-01885
    commandBuffer must not be a protected command buffer

  • VUID-vkCmdBeginQuery-query-00808
    If called within a render pass instance, the sum of query and the number of bits set in the current subpass’s view mask must be less than or equal to the number of queries in queryPool

  • VUID-vkCmdBeginQuery-queryPool-01922
    queryPool must have been created with a queryType that differs from that of any queries that are active within commandBuffer

Valid Usage (Implicit)
  • VUID-vkCmdBeginQuery-commandBuffer-parameter
    commandBuffer must be a valid VkCommandBuffer handle

  • VUID-vkCmdBeginQuery-queryPool-parameter
    queryPool must be a valid VkQueryPool handle

  • VUID-vkCmdBeginQuery-flags-parameter
    flags must be a valid combination of VkQueryControlFlagBits values

  • VUID-vkCmdBeginQuery-commandBuffer-recording
    commandBuffer must be in the recording state

  • VUID-vkCmdBeginQuery-commandBuffer-cmdpool
    The VkCommandPool that commandBuffer was allocated from must support graphics, or compute operations

  • VUID-vkCmdBeginQuery-commonparent
    Both of commandBuffer, and queryPool must have been created, allocated, or retrieved from the same VkDevice

Host Synchronization
  • Host access to commandBuffer must be externally synchronized

  • Host access to the VkCommandPool that commandBuffer was allocated from must be externally synchronized

Command Properties
Command Buffer Levels Render Pass Scope Supported Queue Types Command Type

Primary
Secondary

Both

Graphics
Compute

Action
State

Bits which can be set in vkCmdBeginQuery::flags, specifying constraints on the types of queries that can be performed, are:

// Provided by VK_VERSION_1_0
typedef enum VkQueryControlFlagBits {
    VK_QUERY_CONTROL_PRECISE_BIT = 0x00000001,
} VkQueryControlFlagBits;
// Provided by VK_VERSION_1_0
typedef VkFlags VkQueryControlFlags;

VkQueryControlFlags is a bitmask type for setting a mask of zero or more VkQueryControlFlagBits.

To end a query after the set of desired drawing or dispatching commands is executed, call:

// Provided by VK_VERSION_1_0
void vkCmdEndQuery(
    VkCommandBuffer                             commandBuffer,
    VkQueryPool                                 queryPool,
    uint32_t                                    query);
  • commandBuffer is the command buffer into which this command will be recorded.

  • queryPool is the query pool that is managing the results of the query.

  • query is the query index within the query pool where the result is stored.

The command completes the query in queryPool identified by query, and marks it as available.

This command defines an execution dependency between other query commands that reference the same query.

The first synchronization scope includes all commands which reference the queries in queryPool indicated by query that occur earlier in submission order.

The second synchronization scope includes only the operation of this command.

Valid Usage
  • VUID-vkCmdEndQuery-None-01923
    All queries used by the command must be active

  • VUID-vkCmdEndQuery-query-00810
    query must be less than the number of queries in queryPool

  • VUID-vkCmdEndQuery-commandBuffer-01886
    commandBuffer must not be a protected command buffer

  • VUID-vkCmdEndQuery-query-00812
    If vkCmdEndQuery is called within a render pass instance, the sum of query and the number of bits set in the current subpass’s view mask must be less than or equal to the number of queries in queryPool

  • VUID-vkCmdEndQuery-None-07007
    If called within a subpass of a render pass instance, the corresponding vkCmdBeginQuery* command must have been called previously within the same subpass

Valid Usage (Implicit)
  • VUID-vkCmdEndQuery-commandBuffer-parameter
    commandBuffer must be a valid VkCommandBuffer handle

  • VUID-vkCmdEndQuery-queryPool-parameter
    queryPool must be a valid VkQueryPool handle

  • VUID-vkCmdEndQuery-commandBuffer-recording
    commandBuffer must be in the recording state

  • VUID-vkCmdEndQuery-commandBuffer-cmdpool
    The VkCommandPool that commandBuffer was allocated from must support graphics, or compute operations

  • VUID-vkCmdEndQuery-commonparent
    Both of commandBuffer, and queryPool must have been created, allocated, or retrieved from the same VkDevice

Host Synchronization
  • Host access to commandBuffer must be externally synchronized

  • Host access to the VkCommandPool that commandBuffer was allocated from must be externally synchronized

Command Properties
Command Buffer Levels Render Pass Scope Supported Queue Types Command Type

Primary
Secondary

Both

Graphics
Compute

Action
State

An application can retrieve results either by requesting they be written into application-provided memory, or by requesting they be copied into a VkBuffer. In either case, the layout in memory is defined as follows:

  • The first query’s result is written starting at the first byte requested by the command, and each subsequent query’s result begins stride bytes later.

  • Occlusion queries, pipeline statistics queries, and timestamp queries store results in a tightly packed array of unsigned integers, either 32- or 64-bits as requested by the command, storing the numerical results and, if requested, the availability status.

  • If VK_QUERY_RESULT_WITH_AVAILABILITY_BIT is used, the final element of each query’s result is an integer indicating whether the query’s result is available, with any non-zero value indicating that it is available.

  • Occlusion queries write one integer value - the number of samples passed. Pipeline statistics queries write one integer value for each bit that is enabled in the pipelineStatistics when the pool is created, and the statistics values are written in bit order starting from the least significant bit. Timestamp queries write one integer value.

  • If more than one query is retrieved and stride is not at least as large as the size of the array of values corresponding to a single query, the values written to memory are undefined.

To retrieve status and results for a set of queries, call:

// Provided by VK_VERSION_1_0
VkResult vkGetQueryPoolResults(
    VkDevice                                    device,
    VkQueryPool                                 queryPool,
    uint32_t                                    firstQuery,
    uint32_t                                    queryCount,
    size_t                                      dataSize,
    void*                                       pData,
    VkDeviceSize                                stride,
    VkQueryResultFlags                          flags);
  • device is the logical device that owns the query pool.

  • queryPool is the query pool managing the queries containing the desired results.

  • firstQuery is the initial query index.

  • queryCount is the number of queries to read.

  • dataSize is the size in bytes of the buffer pointed to by pData.

  • pData is a pointer to a user-allocated buffer where the results will be written

  • stride is the stride in bytes between results for individual queries within pData.

  • flags is a bitmask of VkQueryResultFlagBits specifying how and when results are returned.

Any results written for a query are written according to a layout dependent on the query type.

If no bits are set in flags, and all requested queries are in the available state, results are written as an array of 32-bit unsigned integer values. Behavior when not all queries are available is described below.

If VK_QUERY_RESULT_WITH_AVAILABILITY_BIT is set, results for all queries in queryPool identified by firstQuery and queryCount are copied to pData, along with an extra availability value written directly after the results of each query and interpreted as an unsigned integer. A value of zero indicates that the results are not yet available, otherwise the query is complete and results are available. The size of the availability values is 64 bits if VK_QUERY_RESULT_64_BIT is set in flags. Otherwise, it is 32 bits.

Note

If VK_QUERY_RESULT_WITH_AVAILABILITY_BIT is set, the layout of data in the buffer is a (result,availability) pair for each query returned, and stride is the stride between each pair.

Results for any available query written by this command are final and represent the final result of the query. If VK_QUERY_RESULT_PARTIAL_BIT is set, then for any query that is unavailable, an intermediate result between zero and the final result value is written for that query. Otherwise, any result written by this command is undefined.

If VK_QUERY_RESULT_64_BIT is set, results and, if returned, availability values for all queries are written as an array of 64-bit values. Otherwise, results and availability values are written as an array of 32-bit values. If an unsigned integer query’s value overflows the result type, the value may either wrap or saturate.

If VK_QUERY_RESULT_WAIT_BIT is set, this command defines an execution dependency with any earlier commands that writes one of the identified queries. The first synchronization scope includes all instances of vkCmdEndQuery, vkCmdWriteTimestamp2, and vkCmdWriteTimestamp that reference any query in queryPool indicated by firstQuery and queryCount. The second synchronization scope includes the host operations of this command.

If VK_QUERY_RESULT_WAIT_BIT is not set, vkGetQueryPoolResults may return VK_NOT_READY if there are queries in the unavailable state.

Note

Applications must take care to ensure that use of the VK_QUERY_RESULT_WAIT_BIT bit has the desired effect.

For example, if a query has been used previously and a command buffer records the commands vkCmdResetQueryPool, vkCmdBeginQuery, and vkCmdEndQuery for that query, then the query will remain in the available state until vkResetQueryPool is called or the vkCmdResetQueryPool command executes on a queue. Applications can use fences or events to ensure that a query has already been reset before checking for its results or availability status. Otherwise, a stale value could be returned from a previous use of the query.

The above also applies when VK_QUERY_RESULT_WAIT_BIT is used in combination with VK_QUERY_RESULT_WITH_AVAILABILITY_BIT. In this case, the returned availability status may reflect the result of a previous use of the query unless vkResetQueryPool is called or the vkCmdResetQueryPool command has been executed since the last use of the query.

Note

Applications can double-buffer query pool usage, with a pool per frame, and reset queries at the end of the frame in which they are read.

Valid Usage
  • VUID-vkGetQueryPoolResults-firstQuery-09436
    firstQuery must be less than the number of queries in queryPool

  • VUID-vkGetQueryPoolResults-firstQuery-09437
    The sum of firstQuery and queryCount must be less than or equal to the number of queries in queryPool

  • VUID-vkGetQueryPoolResults-queryCount-09438
    If queryCount is greater than 1, stride must not be zero

  • VUID-vkGetQueryPoolResults-queryType-09439
    If the queryType used to create queryPool was VK_QUERY_TYPE_TIMESTAMP, flags must not contain VK_QUERY_RESULT_PARTIAL_BIT

  • VUID-vkGetQueryPoolResults-None-09401
    All queries used by the command must not be uninitialized

  • VUID-vkGetQueryPoolResults-flags-02828
    If VK_QUERY_RESULT_64_BIT is not set in flags then pData and stride must be multiples of 4

  • VUID-vkGetQueryPoolResults-flags-00815
    If VK_QUERY_RESULT_64_BIT is set in flags then pData and stride must be multiples of 8

  • VUID-vkGetQueryPoolResults-stride-08993
    If VK_QUERY_RESULT_WITH_AVAILABILITY_BIT is set, stride must be large enough to contain the unsigned integer representing availability in addition to the query result

  • VUID-vkGetQueryPoolResults-dataSize-00817
    dataSize must be large enough to contain the result of each query, as described here

Valid Usage (Implicit)
  • VUID-vkGetQueryPoolResults-device-parameter
    device must be a valid VkDevice handle

  • VUID-vkGetQueryPoolResults-queryPool-parameter
    queryPool must be a valid VkQueryPool handle

  • VUID-vkGetQueryPoolResults-pData-parameter
    pData must be a valid pointer to an array of dataSize bytes

  • VUID-vkGetQueryPoolResults-flags-parameter
    flags must be a valid combination of VkQueryResultFlagBits values

  • VUID-vkGetQueryPoolResults-dataSize-arraylength
    dataSize must be greater than 0

  • VUID-vkGetQueryPoolResults-queryPool-parent
    queryPool must have been created, allocated, or retrieved from device

Return Codes
Success
  • VK_SUCCESS

  • VK_NOT_READY

Failure
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

  • VK_ERROR_DEVICE_LOST

Bits which can be set in vkGetQueryPoolResults::flags and vkCmdCopyQueryPoolResults::flags, specifying how and when results are returned, are:

// Provided by VK_VERSION_1_0
typedef enum VkQueryResultFlagBits {
    VK_QUERY_RESULT_64_BIT = 0x00000001,
    VK_QUERY_RESULT_WAIT_BIT = 0x00000002,
    VK_QUERY_RESULT_WITH_AVAILABILITY_BIT = 0x00000004,
    VK_QUERY_RESULT_PARTIAL_BIT = 0x00000008,
} VkQueryResultFlagBits;
  • VK_QUERY_RESULT_64_BIT specifies the results will be written as an array of 64-bit unsigned integer values. If this bit is not set, the results will be written as an array of 32-bit unsigned integer values.

  • VK_QUERY_RESULT_WAIT_BIT specifies that Vulkan will wait for each query’s status to become available before retrieving its results.

  • VK_QUERY_RESULT_WITH_AVAILABILITY_BIT specifies that the availability status accompanies the results.

  • VK_QUERY_RESULT_PARTIAL_BIT specifies that returning partial results is acceptable.

// Provided by VK_VERSION_1_0
typedef VkFlags VkQueryResultFlags;

VkQueryResultFlags is a bitmask type for setting a mask of zero or more VkQueryResultFlagBits.

To copy query statuses and numerical results directly to buffer memory, call:

// Provided by VK_VERSION_1_0
void vkCmdCopyQueryPoolResults(
    VkCommandBuffer                             commandBuffer,
    VkQueryPool                                 queryPool,
    uint32_t                                    firstQuery,
    uint32_t                                    queryCount,
    VkBuffer                                    dstBuffer,
    VkDeviceSize                                dstOffset,
    VkDeviceSize                                stride,
    VkQueryResultFlags                          flags);
  • commandBuffer is the command buffer into which this command will be recorded.

  • queryPool is the query pool managing the queries containing the desired results.

  • firstQuery is the initial query index.

  • queryCount is the number of queries. firstQuery and queryCount together define a range of queries.

  • dstBuffer is a VkBuffer object that will receive the results of the copy command.

  • dstOffset is an offset into dstBuffer.

  • stride is the stride in bytes between results for individual queries within dstBuffer. The required size of the backing memory for dstBuffer is determined as described above for vkGetQueryPoolResults.

  • flags is a bitmask of VkQueryResultFlagBits specifying how and when results are returned.

Any results written for a query are written according to a layout dependent on the query type.

Results for any query in queryPool identified by firstQuery and queryCount that is available are copied to dstBuffer.

If VK_QUERY_RESULT_WITH_AVAILABILITY_BIT is set, results for all queries in queryPool identified by firstQuery and queryCount are copied to dstBuffer, along with an extra availability value written directly after the results of each query and interpreted as an unsigned integer. A value of zero indicates that the results are not yet available, otherwise the query is complete and results are available.

Results for any available query written by this command are final and represent the final result of the query. If VK_QUERY_RESULT_PARTIAL_BIT is set, then for any query that is unavailable, an intermediate result between zero and the final result value is written for that query. Otherwise, any result written by this command is undefined.

If VK_QUERY_RESULT_64_BIT is set, results and availability values for all queries are written as an array of 64-bit values. Otherwise, results and availability values are written as an array of 32-bit values. If an unsigned integer query’s value overflows the result type, the value may either wrap or saturate.

This command defines an execution dependency between other query commands that reference the same query.

The first synchronization scope includes all commands which reference the queries in queryPool indicated by query that occur earlier in submission order. If flags does not include VK_QUERY_RESULT_WAIT_BIT, vkCmdWriteTimestamp2, vkCmdEndQuery, and vkCmdWriteTimestamp are excluded from this scope.

The second synchronization scope includes all commands which reference the queries in queryPool indicated by query that occur later in submission order.

The operation of this command happens after the first scope and happens before the second scope.

vkCmdCopyQueryPoolResults is considered to be a transfer operation, and its writes to buffer memory must be synchronized using VK_PIPELINE_STAGE_TRANSFER_BIT and VK_ACCESS_TRANSFER_WRITE_BIT before using the results.

Valid Usage
  • VUID-vkCmdCopyQueryPoolResults-firstQuery-09436
    firstQuery must be less than the number of queries in queryPool

  • VUID-vkCmdCopyQueryPoolResults-firstQuery-09437
    The sum of firstQuery and queryCount must be less than or equal to the number of queries in queryPool

  • VUID-vkCmdCopyQueryPoolResults-queryCount-09438
    If queryCount is greater than 1, stride must not be zero

  • VUID-vkCmdCopyQueryPoolResults-queryType-09439
    If the queryType used to create queryPool was VK_QUERY_TYPE_TIMESTAMP, flags must not contain VK_QUERY_RESULT_PARTIAL_BIT

  • VUID-vkCmdCopyQueryPoolResults-None-09402
    All queries used by the command must not be uninitialized when the command is executed

  • VUID-vkCmdCopyQueryPoolResults-dstOffset-00819
    dstOffset must be less than the size of dstBuffer

  • VUID-vkCmdCopyQueryPoolResults-flags-00822
    If VK_QUERY_RESULT_64_BIT is not set in flags then dstOffset and stride must be multiples of 4

  • VUID-vkCmdCopyQueryPoolResults-flags-00823
    If VK_QUERY_RESULT_64_BIT is set in flags then dstOffset and stride must be multiples of 8

  • VUID-vkCmdCopyQueryPoolResults-dstBuffer-00824
    dstBuffer must have enough storage, from dstOffset, to contain the result of each query, as described here

  • VUID-vkCmdCopyQueryPoolResults-dstBuffer-00825
    dstBuffer must have been created with VK_BUFFER_USAGE_TRANSFER_DST_BIT usage flag

  • VUID-vkCmdCopyQueryPoolResults-dstBuffer-00826
    If dstBuffer is non-sparse then it must be bound completely and contiguously to a single VkDeviceMemory object

  • VUID-vkCmdCopyQueryPoolResults-None-07429
    All queries used by the command must not be active

  • VUID-vkCmdCopyQueryPoolResults-None-08752
    All queries used by the command must have been made available by prior executed commands

Valid Usage (Implicit)
  • VUID-vkCmdCopyQueryPoolResults-commandBuffer-parameter
    commandBuffer must be a valid VkCommandBuffer handle

  • VUID-vkCmdCopyQueryPoolResults-queryPool-parameter
    queryPool must be a valid VkQueryPool handle

  • VUID-vkCmdCopyQueryPoolResults-dstBuffer-parameter
    dstBuffer must be a valid VkBuffer handle

  • VUID-vkCmdCopyQueryPoolResults-flags-parameter
    flags must be a valid combination of VkQueryResultFlagBits values

  • VUID-vkCmdCopyQueryPoolResults-commandBuffer-recording
    commandBuffer must be in the recording state

  • VUID-vkCmdCopyQueryPoolResults-commandBuffer-cmdpool
    The VkCommandPool that commandBuffer was allocated from must support graphics, or compute operations

  • VUID-vkCmdCopyQueryPoolResults-renderpass
    This command must only be called outside of a render pass instance

  • VUID-vkCmdCopyQueryPoolResults-commonparent
    Each of commandBuffer, dstBuffer, and queryPool must have been created, allocated, or retrieved from the same VkDevice

Host Synchronization
  • Host access to commandBuffer must be externally synchronized

  • Host access to the VkCommandPool that commandBuffer was allocated from must be externally synchronized

Command Properties
Command Buffer Levels Render Pass Scope Supported Queue Types Command Type

Primary
Secondary

Outside

Graphics
Compute

Action

Rendering operations such as clears, MSAA resolves, attachment load/store operations, and blits may count towards the results of queries. This behavior is implementation-dependent and may vary depending on the path used within an implementation. For example, some implementations have several types of clears, some of which may include vertices and some not.

17.3. Occlusion Queries

Occlusion queries track the number of samples that pass the per-fragment tests for a set of drawing commands. As such, occlusion queries are only available on queue families supporting graphics operations. The application can then use these results to inform future rendering decisions. An occlusion query is begun and ended by calling vkCmdBeginQuery and vkCmdEndQuery, respectively. When an occlusion query begins, the count of passing samples always starts at zero. For each drawing command, the count is incremented as described in Sample Counting. If flags does not contain VK_QUERY_CONTROL_PRECISE_BIT an implementation may generate any non-zero result value for the query if the count of passing samples is non-zero.

Note

Not setting VK_QUERY_CONTROL_PRECISE_BIT mode may be more efficient on some implementations, and should be used where it is sufficient to know a boolean result on whether any samples passed the per-fragment tests. In this case, some implementations may only return zero or one, indifferent to the actual number of samples passing the per-fragment tests.

Setting VK_QUERY_CONTROL_PRECISE_BIT does not guarantee that different implementations return the same number of samples in an occlusion query. Some implementations may kill fragments in the pre-rasterization shader stage, and these killed fragments do not contribute to the final result of the query. It is possible that some implementations generate a zero result value for the query, while others generate a non-zero value.

When an occlusion query finishes, the result for that query is marked as available. The application can then either copy the result to a buffer (via vkCmdCopyQueryPoolResults) or request it be put into host memory (via vkGetQueryPoolResults).

Note

If occluding geometry is not drawn first, samples can pass the depth test, but still not be visible in a final image.

17.4. Pipeline Statistics Queries

Pipeline statistics queries allow the application to sample a specified set of VkPipeline counters. These counters are accumulated by Vulkan for a set of either drawing or dispatching commands while a pipeline statistics query is active. As such, pipeline statistics queries are available on queue families supporting either graphics or compute operations. The availability of pipeline statistics queries is indicated by the pipelineStatisticsQuery member of the VkPhysicalDeviceFeatures object (see vkGetPhysicalDeviceFeatures and vkCreateDevice for detecting and requesting this query type on a VkDevice).

A pipeline statistics query is begun and ended by calling vkCmdBeginQuery and vkCmdEndQuery, respectively. When a pipeline statistics query begins, all statistics counters are set to zero. While the query is active, the pipeline type determines which set of statistics are available, but these must be configured on the query pool when it is created. If a statistic counter is issued on a command buffer that does not support the corresponding operation, or the counter corresponds to a shading stage which is missing from any of the pipelines used while the query is active, the value of that counter is undefined after the query has been made available. At least one statistic counter relevant to the operations supported on the recording command buffer must be enabled.

Bits which can be set in VkQueryPoolCreateInfo::pipelineStatistics for query pools and in VkCommandBufferInheritanceInfo::pipelineStatistics for secondary command buffers, individually enabling pipeline statistics counters, are:

// Provided by VK_VERSION_1_0
typedef enum VkQueryPipelineStatisticFlagBits {
    VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT = 0x00000001,
    VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT = 0x00000002,
    VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT = 0x00000004,
    VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT = 0x00000008,
    VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT = 0x00000010,
    VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT = 0x00000020,
    VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT = 0x00000040,
    VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT = 0x00000080,
    VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT = 0x00000100,
    VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT = 0x00000200,
    VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT = 0x00000400,
} VkQueryPipelineStatisticFlagBits;
  • VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT specifies that queries managed by the pool will count the number of vertices processed by the input assembly stage. Vertices corresponding to incomplete primitives may contribute to the count.

  • VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT specifies that queries managed by the pool will count the number of primitives processed by the input assembly stage. If primitive restart is enabled, restarting the primitive topology has no effect on the count. Incomplete primitives may be counted.

  • VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT specifies that queries managed by the pool will count the number of vertex shader invocations. This counter’s value is incremented each time a vertex shader is invoked.

  • VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT specifies that queries managed by the pool will count the number of geometry shader invocations. This counter’s value is incremented each time a geometry shader is invoked. In the case of instanced geometry shaders, the geometry shader invocations count is incremented for each separate instanced invocation.

  • VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT specifies that queries managed by the pool will count the number of primitives generated by geometry shader invocations. The counter’s value is incremented each time the geometry shader emits a primitive. Restarting primitive topology using the SPIR-V instructions OpEndPrimitive or OpEndStreamPrimitive has no effect on the geometry shader output primitives count.

  • VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT specifies that queries managed by the pool will count the number of primitives processed by the Primitive Clipping stage of the pipeline. The counter’s value is incremented each time a primitive reaches the primitive clipping stage.

  • VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT specifies that queries managed by the pool will count the number of primitives output by the Primitive Clipping stage of the pipeline. The counter’s value is incremented each time a primitive passes the primitive clipping stage. The actual number of primitives output by the primitive clipping stage for a particular input primitive is implementation-dependent but must satisfy the following conditions:

    • If at least one vertex of the input primitive lies inside the clipping volume, the counter is incremented by one or more.

    • Otherwise, the counter is incremented by zero or more.

  • VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT specifies that queries managed by the pool will count the number of fragment shader invocations. The counter’s value is incremented each time the fragment shader is invoked.

  • VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT specifies that queries managed by the pool will count the number of patches processed by the tessellation control shader. The counter’s value is incremented once for each patch for which a tessellation control shader is invoked.

  • VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT specifies that queries managed by the pool will count the number of invocations of the tessellation evaluation shader. The counter’s value is incremented each time the tessellation evaluation shader is invoked.

  • VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT specifies that queries managed by the pool will count the number of compute shader invocations. The counter’s value is incremented every time the compute shader is invoked. Implementations may skip the execution of certain compute shader invocations or execute additional compute shader invocations for implementation-dependent reasons as long as the results of rendering otherwise remain unchanged.

These values are intended to measure relative statistics on one implementation. Various device architectures will count these values differently. Any or all counters may be affected by the issues described in Query Operation.

Note

For example, tile-based rendering devices may need to replay the scene multiple times, affecting some of the counts.

If a pipeline has rasterizerDiscardEnable enabled, implementations may discard primitives after the final pre-rasterization shader stage. As a result, if rasterizerDiscardEnable is enabled, the clipping input and output primitives counters may not be incremented.

When a pipeline statistics query finishes, the result for that query is marked as available. The application can copy the result to a buffer (via vkCmdCopyQueryPoolResults), or request it be put into host memory (via vkGetQueryPoolResults).

// Provided by VK_VERSION_1_0
typedef VkFlags VkQueryPipelineStatisticFlags;

VkQueryPipelineStatisticFlags is a bitmask type for setting a mask of zero or more VkQueryPipelineStatisticFlagBits.

17.5. Timestamp Queries

Timestamps provide applications with a mechanism for timing the execution of commands. A timestamp is an integer value generated by the VkPhysicalDevice. Unlike other queries, timestamps do not operate over a range, and so do not use vkCmdBeginQuery or vkCmdEndQuery. The mechanism is built around a set of commands that allow the application to tell the VkPhysicalDevice to write timestamp values to a query pool and then either read timestamp values on the host (using vkGetQueryPoolResults) or copy timestamp values to a VkBuffer (using vkCmdCopyQueryPoolResults). The application can then compute differences between timestamps to determine execution time.

The number of valid bits in a timestamp value is determined by the VkQueueFamilyProperties::timestampValidBits property of the queue on which the timestamp is written. Timestamps are supported on any queue which reports a non-zero value for timestampValidBits via vkGetPhysicalDeviceQueueFamilyProperties. If the timestampComputeAndGraphics limit is VK_TRUE, timestamps are supported by every queue family that supports either graphics or compute operations (see VkQueueFamilyProperties).

The number of nanoseconds it takes for a timestamp value to be incremented by 1 can be obtained from VkPhysicalDeviceLimits::timestampPeriod after a call to vkGetPhysicalDeviceProperties.

To request a timestamp and write the value to memory, call:

// Provided by VK_VERSION_1_3
void vkCmdWriteTimestamp2(
    VkCommandBuffer                             commandBuffer,
    VkPipelineStageFlags2                       stage,
    VkQueryPool                                 queryPool,
    uint32_t                                    query);
  • commandBuffer is the command buffer into which the command will be recorded.

  • stage specifies a stage of the pipeline.

  • queryPool is the query pool that will manage the timestamp.

  • query is the query within the query pool that will contain the timestamp.

When vkCmdWriteTimestamp2 is submitted to a queue, it defines an execution dependency on commands that were submitted before it, and writes a timestamp to a query pool.

The first synchronization scope includes all commands that occur earlier in submission order. The synchronization scope is limited to operations on the pipeline stage specified by stage.

The second synchronization scope includes only the timestamp write operation.

Note

Implementations may write the timestamp at any stage that is logically later than stage.

Any timestamp write that happens-after another timestamp write in the same submission must not have a lower value unless its value overflows the maximum supported integer bit width of the query. If an overflow occurs, the timestamp value must wrap back to zero.

Note

Comparisons between timestamps should be done between timestamps where they are guaranteed to not decrease. For example, subtracting an older timestamp from a newer one to determine the execution time of a sequence of commands is only a reliable measurement if the two timestamp writes were performed in the same submission.

If vkCmdWriteTimestamp2 is called while executing a render pass instance that has multiview enabled, the timestamp uses N consecutive query indices in the query pool (starting at query) where N is the number of bits set in the view mask of the subpass the command is executed in. The resulting query values are determined by an implementation-dependent choice of one of the following behaviors:

  • The first query is a timestamp value and (if more than one bit is set in the view mask) zero is written to the remaining queries. If two timestamps are written in the same subpass, the sum of the execution time of all views between those commands is the difference between the first query written by each command.

  • All N queries are timestamp values. If two timestamps are written in the same subpass, the sum of the execution time of all views between those commands is the sum of the difference between corresponding queries written by each command. The difference between corresponding queries may be the execution time of a single view.

In either case, the application can sum the differences between all N queries to determine the total execution time.

Valid Usage
  • VUID-vkCmdWriteTimestamp2-stage-03929
    If the geometryShader feature is not enabled, stage must not contain VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT

  • VUID-vkCmdWriteTimestamp2-stage-03930
    If the tessellationShader feature is not enabled, stage must not contain VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT or VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT

  • VUID-vkCmdWriteTimestamp2-synchronization2-03858
    The synchronization2 feature must be enabled

  • VUID-vkCmdWriteTimestamp2-stage-03859
    stage must only include a single pipeline stage

  • VUID-vkCmdWriteTimestamp2-stage-03860
    stage must only include stages valid for the queue family that was used to create the command pool that commandBuffer was allocated from

  • VUID-vkCmdWriteTimestamp2-queryPool-03861
    queryPool must have been created with a queryType of VK_QUERY_TYPE_TIMESTAMP

  • VUID-vkCmdWriteTimestamp2-timestampValidBits-03863
    The command pool’s queue family must support a non-zero timestampValidBits

  • VUID-vkCmdWriteTimestamp2-query-04903
    query must be less than the number of queries in queryPool

  • VUID-vkCmdWriteTimestamp2-None-03864
    All queries used by the command must be unavailable

  • VUID-vkCmdWriteTimestamp2-query-03865
    If vkCmdWriteTimestamp2 is called within a render pass instance, the sum of query and the number of bits set in the current subpass’s view mask must be less than or equal to the number of queries in queryPool

Valid Usage (Implicit)
  • VUID-vkCmdWriteTimestamp2-commandBuffer-parameter
    commandBuffer must be a valid VkCommandBuffer handle

  • VUID-vkCmdWriteTimestamp2-stage-parameter
    stage must be a valid combination of VkPipelineStageFlagBits2 values

  • VUID-vkCmdWriteTimestamp2-queryPool-parameter
    queryPool must be a valid VkQueryPool handle

  • VUID-vkCmdWriteTimestamp2-commandBuffer-recording
    commandBuffer must be in the recording state

  • VUID-vkCmdWriteTimestamp2-commandBuffer-cmdpool
    The VkCommandPool that commandBuffer was allocated from must support transfer, graphics, or compute operations

  • VUID-vkCmdWriteTimestamp2-commonparent
    Both of commandBuffer, and queryPool must have been created, allocated, or retrieved from the same VkDevice

Host Synchronization
  • Host access to commandBuffer must be externally synchronized

  • Host access to the VkCommandPool that commandBuffer was allocated from must be externally synchronized

Command Properties
Command Buffer Levels Render Pass Scope Supported Queue Types Command Type

Primary
Secondary

Both

Transfer
Graphics
Compute

Action

To request a timestamp and write the value to memory, call:

// Provided by VK_VERSION_1_0
void vkCmdWriteTimestamp(
    VkCommandBuffer                             commandBuffer,
    VkPipelineStageFlagBits                     pipelineStage,
    VkQueryPool                                 queryPool,
    uint32_t                                    query);
  • commandBuffer is the command buffer into which the command will be recorded.

  • pipelineStage is a VkPipelineStageFlagBits value, specifying a stage of the pipeline.

  • queryPool is the query pool that will manage the timestamp.

  • query is the query within the query pool that will contain the timestamp.

When vkCmdWriteTimestamp is submitted to a queue, it defines an execution dependency on commands that were submitted before it, and writes a timestamp to a query pool.

The first synchronization scope includes all commands that occur earlier in submission order. The synchronization scope is limited to operations on the pipeline stage specified by pipelineStage.

The second synchronization scope includes only the timestamp write operation.

Note

Implementations may write the timestamp at any stage that is logically later than stage.

Any timestamp write that happens-after another timestamp write in the same submission must not have a lower value unless its value overflows the maximum supported integer bit width of the query. If an overflow occurs, the timestamp value must wrap back to zero.

Note

Comparisons between timestamps should be done between timestamps where they are guaranteed to not decrease. For example, subtracting an older timestamp from a newer one to determine the execution time of a sequence of commands is only a reliable measurement if the two timestamp writes were performed in the same submission.

If vkCmdWriteTimestamp is called while executing a render pass instance that has multiview enabled, the timestamp uses N consecutive query indices in the query pool (starting at query) where N is the number of bits set in the view mask of the subpass the command is executed in. The resulting query values are determined by an implementation-dependent choice of one of the following behaviors:

  • The first query is a timestamp value and (if more than one bit is set in the view mask) zero is written to the remaining queries. If two timestamps are written in the same subpass, the sum of the execution time of all views between those commands is the difference between the first query written by each command.

  • All N queries are timestamp values. If two timestamps are written in the same subpass, the sum of the execution time of all views between those commands is the sum of the difference between corresponding queries written by each command. The difference between corresponding queries may be the execution time of a single view.

In either case, the application can sum the differences between all N queries to determine the total execution time.

Valid Usage
  • VUID-vkCmdWriteTimestamp-pipelineStage-04074
    pipelineStage must be a valid stage for the queue family that was used to create the command pool that commandBuffer was allocated from

  • VUID-vkCmdWriteTimestamp-pipelineStage-04075
    If the geometryShader feature is not enabled, pipelineStage must not be VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT

  • VUID-vkCmdWriteTimestamp-pipelineStage-04076
    If the tessellationShader feature is not enabled, pipelineStage must not be VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT or VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT

  • VUID-vkCmdWriteTimestamp-synchronization2-06489
    If the synchronization2 feature is not enabled, pipelineStage must not be VK_PIPELINE_STAGE_NONE

  • VUID-vkCmdWriteTimestamp-queryPool-01416
    queryPool must have been created with a queryType of VK_QUERY_TYPE_TIMESTAMP

  • VUID-vkCmdWriteTimestamp-timestampValidBits-00829
    The command pool’s queue family must support a non-zero timestampValidBits

  • VUID-vkCmdWriteTimestamp-query-04904
    query must be less than the number of queries in queryPool

  • VUID-vkCmdWriteTimestamp-None-00830
    All queries used by the command must be unavailable

  • VUID-vkCmdWriteTimestamp-query-00831
    If vkCmdWriteTimestamp is called within a render pass instance, the sum of query and the number of bits set in the current subpass’s view mask must be less than or equal to the number of queries in queryPool

Valid Usage (Implicit)
  • VUID-vkCmdWriteTimestamp-commandBuffer-parameter
    commandBuffer must be a valid VkCommandBuffer handle

  • VUID-vkCmdWriteTimestamp-pipelineStage-parameter
    pipelineStage must be a valid VkPipelineStageFlagBits value

  • VUID-vkCmdWriteTimestamp-queryPool-parameter
    queryPool must be a valid VkQueryPool handle

  • VUID-vkCmdWriteTimestamp-commandBuffer-recording
    commandBuffer must be in the recording state

  • VUID-vkCmdWriteTimestamp-commandBuffer-cmdpool
    The VkCommandPool that commandBuffer was allocated from must support transfer, graphics, or compute operations

  • VUID-vkCmdWriteTimestamp-commonparent
    Both of commandBuffer, and queryPool must have been created, allocated, or retrieved from the same VkDevice

Host Synchronization
  • Host access to commandBuffer must be externally synchronized

  • Host access to the VkCommandPool that commandBuffer was allocated from must be externally synchronized

Command Properties
Command Buffer Levels Render Pass Scope Supported Queue Types Command Type

Primary
Secondary

Both

Transfer
Graphics
Compute

Action