Alexis Hetu | 86f8bdb | 2019-01-22 12:07:24 -0500 | [diff] [blame] | 1 | // Copyright 2018 The SwiftShader Authors. All Rights Reserved. |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | #include "VkQueryPool.hpp" |
Alexis Hetu | f0aa9d5 | 2019-04-01 17:06:47 -0400 | [diff] [blame] | 16 | |
| 17 | #include <chrono> |
| 18 | #include <cstring> |
| 19 | #include <new> |
Alexis Hetu | 86f8bdb | 2019-01-22 12:07:24 -0500 | [diff] [blame] | 20 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 21 | namespace vk { |
| 22 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 23 | Query::Query() |
| 24 | : finished(marl::Event::Mode::Manual) |
| 25 | , state(UNAVAILABLE) |
| 26 | , type(INVALID_TYPE) |
| 27 | , value(0) |
| 28 | {} |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 29 | |
| 30 | void Query::reset() |
Alexis Hetu | 86f8bdb | 2019-01-22 12:07:24 -0500 | [diff] [blame] | 31 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 32 | finished.clear(); |
| 33 | auto prevState = state.exchange(UNAVAILABLE); |
| 34 | ASSERT(prevState != ACTIVE); |
| 35 | type = INVALID_TYPE; |
| 36 | value = 0; |
| 37 | } |
Ben Clayton | b03ce83 | 2019-05-21 19:56:58 +0100 | [diff] [blame] | 38 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 39 | void Query::prepare(VkQueryType ty) |
| 40 | { |
| 41 | auto prevState = state.exchange(ACTIVE); |
| 42 | ASSERT(prevState == UNAVAILABLE); |
| 43 | type = ty; |
| 44 | } |
| 45 | |
| 46 | void Query::start() |
| 47 | { |
| 48 | ASSERT(state == ACTIVE); |
| 49 | wg.add(); |
| 50 | } |
| 51 | |
| 52 | void Query::finish() |
| 53 | { |
Nicolas Capens | 81bc9d9 | 2019-12-16 15:05:57 -0500 | [diff] [blame] | 54 | if(wg.done()) |
Ben Clayton | b03ce83 | 2019-05-21 19:56:58 +0100 | [diff] [blame] | 55 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 56 | auto prevState = state.exchange(FINISHED); |
| 57 | ASSERT(prevState == ACTIVE); |
| 58 | finished.signal(); |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | Query::Data Query::getData() const |
| 63 | { |
| 64 | Data out; |
| 65 | out.state = state; |
| 66 | out.value = value; |
| 67 | return out; |
| 68 | } |
| 69 | |
| 70 | VkQueryType Query::getType() const |
| 71 | { |
| 72 | return type; |
| 73 | } |
| 74 | |
| 75 | void Query::wait() |
| 76 | { |
| 77 | finished.wait(); |
| 78 | } |
| 79 | |
| 80 | void Query::set(int64_t v) |
| 81 | { |
| 82 | value = v; |
| 83 | } |
| 84 | |
| 85 | void Query::add(int64_t v) |
| 86 | { |
| 87 | value += v; |
| 88 | } |
| 89 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 90 | QueryPool::QueryPool(const VkQueryPoolCreateInfo *pCreateInfo, void *mem) |
| 91 | : pool(reinterpret_cast<Query *>(mem)) |
| 92 | , type(pCreateInfo->queryType) |
| 93 | , count(pCreateInfo->queryCount) |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 94 | { |
Nicolas Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 95 | // According to the Vulkan 1.2 spec, section 30. Features: |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 96 | // "pipelineStatisticsQuery specifies whether the pipeline statistics |
| 97 | // queries are supported. If this feature is not enabled, queries of |
| 98 | // type VK_QUERY_TYPE_PIPELINE_STATISTICS cannot be created, and |
| 99 | // none of the VkQueryPipelineStatisticFlagBits bits can be set in the |
| 100 | // pipelineStatistics member of the VkQueryPoolCreateInfo structure." |
| 101 | if(type == VK_QUERY_TYPE_PIPELINE_STATISTICS) |
| 102 | { |
Nicolas Capens | 44bd43a | 2020-01-22 03:07:14 -0500 | [diff] [blame] | 103 | UNSUPPORTED("VkPhysicalDeviceFeatures::pipelineStatisticsQuery"); |
Ben Clayton | b03ce83 | 2019-05-21 19:56:58 +0100 | [diff] [blame] | 104 | } |
| 105 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 106 | // Construct all queries |
| 107 | for(uint32_t i = 0; i < count; i++) |
Ben Clayton | b03ce83 | 2019-05-21 19:56:58 +0100 | [diff] [blame] | 108 | { |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 109 | new(&pool[i]) Query(); |
Ben Clayton | b03ce83 | 2019-05-21 19:56:58 +0100 | [diff] [blame] | 110 | } |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 111 | } |
Ben Clayton | b03ce83 | 2019-05-21 19:56:58 +0100 | [diff] [blame] | 112 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 113 | void QueryPool::destroy(const VkAllocationCallbacks *pAllocator) |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 114 | { |
Ben Clayton | b8d4792 | 2020-04-04 11:22:35 +0100 | [diff] [blame] | 115 | for(uint32_t i = 0; i < count; i++) |
| 116 | { |
| 117 | pool[i].~Query(); |
| 118 | } |
| 119 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 120 | vk::deallocate(pool, pAllocator); |
| 121 | } |
Ben Clayton | b03ce83 | 2019-05-21 19:56:58 +0100 | [diff] [blame] | 122 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 123 | size_t QueryPool::ComputeRequiredAllocationSize(const VkQueryPoolCreateInfo *pCreateInfo) |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 124 | { |
| 125 | return sizeof(Query) * pCreateInfo->queryCount; |
| 126 | } |
| 127 | |
| 128 | VkResult QueryPool::getResults(uint32_t firstQuery, uint32_t queryCount, size_t dataSize, |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 129 | void *pData, VkDeviceSize stride, VkQueryResultFlags flags) const |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 130 | { |
| 131 | // dataSize must be large enough to contain the result of each query |
| 132 | ASSERT(static_cast<size_t>(stride * queryCount) <= dataSize); |
| 133 | |
| 134 | // The sum of firstQuery and queryCount must be less than or equal to the number of queries |
| 135 | ASSERT((firstQuery + queryCount) <= count); |
| 136 | |
| 137 | VkResult result = VK_SUCCESS; |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 138 | uint8_t *data = static_cast<uint8_t *>(pData); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 139 | for(uint32_t i = firstQuery; i < (firstQuery + queryCount); i++, data += stride) |
Ben Clayton | b03ce83 | 2019-05-21 19:56:58 +0100 | [diff] [blame] | 140 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 141 | // If VK_QUERY_RESULT_WAIT_BIT and VK_QUERY_RESULT_PARTIAL_BIT are both not set |
| 142 | // then no result values are written to pData for queries that are in the |
| 143 | // unavailable state at the time of the call, and vkGetQueryPoolResults returns |
| 144 | // VK_NOT_READY. However, availability state is still written to pData for those |
| 145 | // queries if VK_QUERY_RESULT_WITH_AVAILABILITY_BIT is set. |
| 146 | auto &query = pool[i]; |
| 147 | |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 148 | if(flags & VK_QUERY_RESULT_WAIT_BIT) // Must wait for query to finish |
Ben Clayton | b03ce83 | 2019-05-21 19:56:58 +0100 | [diff] [blame] | 149 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 150 | query.wait(); |
Alexis Hetu | 86f8bdb | 2019-01-22 12:07:24 -0500 | [diff] [blame] | 151 | } |
Alexis Hetu | f0aa9d5 | 2019-04-01 17:06:47 -0400 | [diff] [blame] | 152 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 153 | const auto current = query.getData(); |
| 154 | |
| 155 | bool writeResult = true; |
| 156 | if(current.state == Query::ACTIVE) |
Alexis Hetu | f0aa9d5 | 2019-04-01 17:06:47 -0400 | [diff] [blame] | 157 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 158 | result = VK_NOT_READY; |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 159 | writeResult = (flags & VK_QUERY_RESULT_PARTIAL_BIT); // Allow writing partial results |
Alexis Hetu | f0aa9d5 | 2019-04-01 17:06:47 -0400 | [diff] [blame] | 160 | } |
Alexis Hetu | f0aa9d5 | 2019-04-01 17:06:47 -0400 | [diff] [blame] | 161 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 162 | if(flags & VK_QUERY_RESULT_64_BIT) |
Alexis Hetu | 86f8bdb | 2019-01-22 12:07:24 -0500 | [diff] [blame] | 163 | { |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 164 | uint64_t *result64 = reinterpret_cast<uint64_t *>(data); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 165 | if(writeResult) |
Alexis Hetu | f0aa9d5 | 2019-04-01 17:06:47 -0400 | [diff] [blame] | 166 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 167 | result64[0] = current.value; |
Alexis Hetu | f0aa9d5 | 2019-04-01 17:06:47 -0400 | [diff] [blame] | 168 | } |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 169 | if(flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) // Output query availablity |
Alexis Hetu | f0aa9d5 | 2019-04-01 17:06:47 -0400 | [diff] [blame] | 170 | { |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 171 | result64[1] = current.state; |
Alexis Hetu | f0aa9d5 | 2019-04-01 17:06:47 -0400 | [diff] [blame] | 172 | } |
Alexis Hetu | 86f8bdb | 2019-01-22 12:07:24 -0500 | [diff] [blame] | 173 | } |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 174 | else |
Alexis Hetu | f0aa9d5 | 2019-04-01 17:06:47 -0400 | [diff] [blame] | 175 | { |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 176 | uint32_t *result32 = reinterpret_cast<uint32_t *>(data); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 177 | if(writeResult) |
| 178 | { |
| 179 | result32[0] = static_cast<uint32_t>(current.value); |
| 180 | } |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 181 | if(flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) // Output query availablity |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 182 | { |
| 183 | result32[1] = current.state; |
| 184 | } |
Alexis Hetu | f0aa9d5 | 2019-04-01 17:06:47 -0400 | [diff] [blame] | 185 | } |
| 186 | } |
| 187 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 188 | return result; |
| 189 | } |
Alexis Hetu | f0aa9d5 | 2019-04-01 17:06:47 -0400 | [diff] [blame] | 190 | |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 191 | void QueryPool::begin(uint32_t query, VkQueryControlFlags flags) |
| 192 | { |
| 193 | ASSERT(query < count); |
| 194 | |
| 195 | if(flags != 0) |
| 196 | { |
Nicolas Capens | dd0e600 | 2020-01-24 01:21:47 -0500 | [diff] [blame] | 197 | UNSUPPORTED("vkCmdBeginQuery::flags %d", int(flags)); |
Alexis Hetu | 86f8bdb | 2019-01-22 12:07:24 -0500 | [diff] [blame] | 198 | } |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 199 | |
| 200 | pool[query].prepare(type); |
| 201 | pool[query].start(); |
| 202 | } |
| 203 | |
| 204 | void QueryPool::end(uint32_t query) |
| 205 | { |
| 206 | ASSERT(query < count); |
| 207 | pool[query].finish(); |
| 208 | } |
| 209 | |
| 210 | void QueryPool::reset(uint32_t firstQuery, uint32_t queryCount) |
| 211 | { |
| 212 | // The sum of firstQuery and queryCount must be less than or equal to the number of queries |
| 213 | ASSERT((firstQuery + queryCount) <= count); |
| 214 | |
| 215 | for(uint32_t i = firstQuery; i < (firstQuery + queryCount); i++) |
| 216 | { |
| 217 | pool[i].reset(); |
| 218 | } |
| 219 | } |
| 220 | |
| 221 | void QueryPool::writeTimestamp(uint32_t query) |
| 222 | { |
| 223 | ASSERT(query < count); |
| 224 | ASSERT(type == VK_QUERY_TYPE_TIMESTAMP); |
| 225 | |
| 226 | pool[query].set(std::chrono::time_point_cast<std::chrono::nanoseconds>( |
Ben Clayton | 2ed93ab | 2019-12-17 20:38:03 +0000 | [diff] [blame] | 227 | std::chrono::system_clock::now()) |
| 228 | .time_since_epoch() |
| 229 | .count()); |
Nicolas Capens | 157ba26 | 2019-12-10 17:49:14 -0500 | [diff] [blame] | 230 | } |
| 231 | |
| 232 | } // namespace vk |