# vkCmdCopyQueryPoolResults(3) Manual Page

## Name

vkCmdCopyQueryPoolResults - Copy the results of queries in a query pool to a buffer object

## C Specification

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

    void vkCmdCopyQueryPoolResults(
        VkCommandBuffer                             commandBuffer,
        VkQueryPool                                 queryPool,
        uint32_t                                    firstQuery,
        uint32_t                                    queryCount,
        VkBuffer                                    dstBuffer,
        VkDeviceSize                                dstOffset,
        VkDeviceSize                                stride,
        VkQueryResultFlags                          flags);

## Parameters

- `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.

## Description

`vkCmdCopyQueryPoolResults` is guaranteed to see the effect of previous uses of `vkCmdResetQueryPool` in the same queue, without any additional synchronization. Thus, the results will always reflect the most recent use of the query.

`flags` has the same possible values described above for the `flags` parameter of vkGetQueryPoolResults, but the different style of execution causes some subtle behavioral differences. Because `vkCmdCopyQueryPoolResults` executes in order with respect to other query commands, there is less ambiguity about which use of a query is being requested.

Results for all requested occlusion queries, pipeline statistics queries, transform feedback queries, and timestamp queries are written as 64-bit unsigned integer values if `VK_QUERY_RESULT_64_BIT` is set or 32-bit unsigned integer values otherwise. Performance queries store results in a tightly packed array whose type is determined by the `unit` member of the corresponding VkPerformanceCounterKHR.

If neither of `VK_QUERY_RESULT_WAIT_BIT` and `VK_QUERY_RESULT_WITH_AVAILABILITY_BIT` are set, results are only written out for queries in the available state.

If `VK_QUERY_RESULT_WAIT_BIT` is set, the implementation will wait for each query’s status to be in the available state before retrieving the numerical results for that query. This is guaranteed to reflect the most recent use of the query on the same queue, assuming that the query is not being simultaneously used by other queues. If the query does not become available in a finite amount of time (e.g. due to not issuing a query since the last reset), a `VK_ERROR_DEVICE_LOST` error may occur.

Similarly, if `VK_QUERY_RESULT_WITH_AVAILABILITY_BIT` is set and `VK_QUERY_RESULT_WAIT_BIT` is not set, the availability is guaranteed to reflect the most recent use of the query on the same queue, assuming that the query is not being simultaneously used by other queues. As with `vkGetQueryPoolResults`, implementations must guarantee that if they return a non-zero availability value, then the numerical results are valid.

If `VK_QUERY_RESULT_PARTIAL_BIT` is set, `VK_QUERY_RESULT_WAIT_BIT` is not set, and the query’s status is unavailable, an intermediate result value between zero and the final result value is written for that query.

`VK_QUERY_RESULT_PARTIAL_BIT` must not be used if the pool’s `queryType` is `VK_QUERY_TYPE_TIMESTAMP`.

`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

- `dstOffset` must be less than the size of `dstBuffer`

- `firstQuery` must be less than the number of queries in `queryPool`

- The sum of `firstQuery` and `queryCount` must be less than or equal to the number of queries in `queryPool`

- If `VK_QUERY_RESULT_64_BIT` is not set in `flags` then `dstOffset` and `stride` must be multiples of `4`

- If `VK_QUERY_RESULT_64_BIT` is set in `flags` then `dstOffset` and `stride` must be multiples of `8`

- `dstBuffer` must have enough storage, from `dstOffset`, to contain the result of each query, as described here

- `dstBuffer` must have been created with `VK_BUFFER_USAGE_TRANSFER_DST_BIT` usage flag

- If `dstBuffer` is non-sparse then it must be bound completely and contiguously to a single `VkDeviceMemory` object

- If the `queryType` used to create `queryPool` was `VK_QUERY_TYPE_TIMESTAMP`, `flags` must not contain `VK_QUERY_RESULT_PARTIAL_BIT`

- If the `queryType` used to create `queryPool` was `VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR`, VkPhysicalDevicePerformanceQueryPropertiesKHR::`allowCommandBufferQueryCopies` must be `VK_TRUE`

- If the `queryType` used to create `queryPool` was `VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR`, `flags` must not contain `VK_QUERY_RESULT_WITH_AVAILABILITY_BIT`, `VK_QUERY_RESULT_PARTIAL_BIT` or `VK_QUERY_RESULT_64_BIT`

- If the `queryType` used to create `queryPool` was `VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR`, the `queryPool` must have been submitted once for each pass as retrieved via a call to vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR

- vkCmdCopyQueryPoolResults must not be called if the `queryType` used to create `queryPool` was `VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL`

Valid Usage (Implicit)

- `commandBuffer` must be a valid VkCommandBuffer handle

- `queryPool` must be a valid VkQueryPool handle

- `dstBuffer` must be a valid VkBuffer handle

- `flags` must be a valid combination of VkQueryResultFlagBits values

- `commandBuffer` must be in the recording state

- The `VkCommandPool` that `commandBuffer` was allocated from must support graphics, or compute operations

- This command must only be called outside of a render pass instance

- 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 | Pipeline Type
--- | --- | --- | ---
Primary Secondary | Outside | Graphics Compute | Transfer

## See Also

VkBuffer, VkCommandBuffer, `VkDeviceSize`, VkQueryPool, VkQueryResultFlags

## Document Notes

For more information, see the Vulkan Specification

This page is extracted from the Vulkan Specification. Fixes and changes should be made to the Specification, not directly.

## Copyright

Copyright (c) 2014-2020 Khronos Group. This work is licensed under a Creative Commons Attribution 4.0 International License.