blob: b3136205eb5a44ffeb6caa162f8ad1aaf5446845 [file] [log] [blame]
Alexis Hetu86f8bdb2019-01-22 12:07:24 -05001// 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 Hetuf0aa9d52019-04-01 17:06:47 -040016
17#include <chrono>
18#include <cstring>
19#include <new>
Alexis Hetu86f8bdb2019-01-22 12:07:24 -050020
Nicolas Capens157ba262019-12-10 17:49:14 -050021namespace vk {
22
Ben Clayton2ed93ab2019-12-17 20:38:03 +000023Query::Query()
24 : finished(marl::Event::Mode::Manual)
25 , state(UNAVAILABLE)
26 , type(INVALID_TYPE)
27 , value(0)
28{}
Nicolas Capens157ba262019-12-10 17:49:14 -050029
30void Query::reset()
Alexis Hetu86f8bdb2019-01-22 12:07:24 -050031{
Nicolas Capens157ba262019-12-10 17:49:14 -050032 finished.clear();
33 auto prevState = state.exchange(UNAVAILABLE);
34 ASSERT(prevState != ACTIVE);
35 type = INVALID_TYPE;
36 value = 0;
37}
Ben Claytonb03ce832019-05-21 19:56:58 +010038
Nicolas Capens157ba262019-12-10 17:49:14 -050039void Query::prepare(VkQueryType ty)
40{
41 auto prevState = state.exchange(ACTIVE);
42 ASSERT(prevState == UNAVAILABLE);
43 type = ty;
44}
45
46void Query::start()
47{
48 ASSERT(state == ACTIVE);
49 wg.add();
50}
51
52void Query::finish()
53{
Nicolas Capens81bc9d92019-12-16 15:05:57 -050054 if(wg.done())
Ben Claytonb03ce832019-05-21 19:56:58 +010055 {
Nicolas Capens157ba262019-12-10 17:49:14 -050056 auto prevState = state.exchange(FINISHED);
57 ASSERT(prevState == ACTIVE);
58 finished.signal();
59 }
60}
61
62Query::Data Query::getData() const
63{
64 Data out;
65 out.state = state;
66 out.value = value;
67 return out;
68}
69
70VkQueryType Query::getType() const
71{
72 return type;
73}
74
75void Query::wait()
76{
77 finished.wait();
78}
79
80void Query::set(int64_t v)
81{
82 value = v;
83}
84
85void Query::add(int64_t v)
86{
87 value += v;
88}
89
Ben Clayton2ed93ab2019-12-17 20:38:03 +000090QueryPool::QueryPool(const VkQueryPoolCreateInfo *pCreateInfo, void *mem)
91 : pool(reinterpret_cast<Query *>(mem))
92 , type(pCreateInfo->queryType)
93 , count(pCreateInfo->queryCount)
Nicolas Capens157ba262019-12-10 17:49:14 -050094{
Nicolas Capens44bd43a2020-01-22 03:07:14 -050095 // According to the Vulkan 1.2 spec, section 30. Features:
Nicolas Capens157ba262019-12-10 17:49:14 -050096 // "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 Capens44bd43a2020-01-22 03:07:14 -0500103 UNSUPPORTED("VkPhysicalDeviceFeatures::pipelineStatisticsQuery");
Ben Claytonb03ce832019-05-21 19:56:58 +0100104 }
105
Nicolas Capens157ba262019-12-10 17:49:14 -0500106 // Construct all queries
107 for(uint32_t i = 0; i < count; i++)
Ben Claytonb03ce832019-05-21 19:56:58 +0100108 {
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000109 new(&pool[i]) Query();
Ben Claytonb03ce832019-05-21 19:56:58 +0100110 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500111}
Ben Claytonb03ce832019-05-21 19:56:58 +0100112
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000113void QueryPool::destroy(const VkAllocationCallbacks *pAllocator)
Nicolas Capens157ba262019-12-10 17:49:14 -0500114{
Ben Claytonb8d47922020-04-04 11:22:35 +0100115 for(uint32_t i = 0; i < count; i++)
116 {
117 pool[i].~Query();
118 }
119
Nicolas Capens157ba262019-12-10 17:49:14 -0500120 vk::deallocate(pool, pAllocator);
121}
Ben Claytonb03ce832019-05-21 19:56:58 +0100122
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000123size_t QueryPool::ComputeRequiredAllocationSize(const VkQueryPoolCreateInfo *pCreateInfo)
Nicolas Capens157ba262019-12-10 17:49:14 -0500124{
125 return sizeof(Query) * pCreateInfo->queryCount;
126}
127
128VkResult QueryPool::getResults(uint32_t firstQuery, uint32_t queryCount, size_t dataSize,
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000129 void *pData, VkDeviceSize stride, VkQueryResultFlags flags) const
Nicolas Capens157ba262019-12-10 17:49:14 -0500130{
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 Clayton2ed93ab2019-12-17 20:38:03 +0000138 uint8_t *data = static_cast<uint8_t *>(pData);
Nicolas Capens157ba262019-12-10 17:49:14 -0500139 for(uint32_t i = firstQuery; i < (firstQuery + queryCount); i++, data += stride)
Ben Claytonb03ce832019-05-21 19:56:58 +0100140 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500141 // 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 Clayton2ed93ab2019-12-17 20:38:03 +0000148 if(flags & VK_QUERY_RESULT_WAIT_BIT) // Must wait for query to finish
Ben Claytonb03ce832019-05-21 19:56:58 +0100149 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500150 query.wait();
Alexis Hetu86f8bdb2019-01-22 12:07:24 -0500151 }
Alexis Hetuf0aa9d52019-04-01 17:06:47 -0400152
Nicolas Capens157ba262019-12-10 17:49:14 -0500153 const auto current = query.getData();
154
155 bool writeResult = true;
156 if(current.state == Query::ACTIVE)
Alexis Hetuf0aa9d52019-04-01 17:06:47 -0400157 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500158 result = VK_NOT_READY;
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000159 writeResult = (flags & VK_QUERY_RESULT_PARTIAL_BIT); // Allow writing partial results
Alexis Hetuf0aa9d52019-04-01 17:06:47 -0400160 }
Alexis Hetuf0aa9d52019-04-01 17:06:47 -0400161
Nicolas Capens157ba262019-12-10 17:49:14 -0500162 if(flags & VK_QUERY_RESULT_64_BIT)
Alexis Hetu86f8bdb2019-01-22 12:07:24 -0500163 {
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000164 uint64_t *result64 = reinterpret_cast<uint64_t *>(data);
Nicolas Capens157ba262019-12-10 17:49:14 -0500165 if(writeResult)
Alexis Hetuf0aa9d52019-04-01 17:06:47 -0400166 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500167 result64[0] = current.value;
Alexis Hetuf0aa9d52019-04-01 17:06:47 -0400168 }
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000169 if(flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) // Output query availablity
Alexis Hetuf0aa9d52019-04-01 17:06:47 -0400170 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500171 result64[1] = current.state;
Alexis Hetuf0aa9d52019-04-01 17:06:47 -0400172 }
Alexis Hetu86f8bdb2019-01-22 12:07:24 -0500173 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500174 else
Alexis Hetuf0aa9d52019-04-01 17:06:47 -0400175 {
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000176 uint32_t *result32 = reinterpret_cast<uint32_t *>(data);
Nicolas Capens157ba262019-12-10 17:49:14 -0500177 if(writeResult)
178 {
179 result32[0] = static_cast<uint32_t>(current.value);
180 }
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000181 if(flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) // Output query availablity
Nicolas Capens157ba262019-12-10 17:49:14 -0500182 {
183 result32[1] = current.state;
184 }
Alexis Hetuf0aa9d52019-04-01 17:06:47 -0400185 }
186 }
187
Nicolas Capens157ba262019-12-10 17:49:14 -0500188 return result;
189}
Alexis Hetuf0aa9d52019-04-01 17:06:47 -0400190
Nicolas Capens157ba262019-12-10 17:49:14 -0500191void QueryPool::begin(uint32_t query, VkQueryControlFlags flags)
192{
193 ASSERT(query < count);
194
195 if(flags != 0)
196 {
Nicolas Capensdd0e6002020-01-24 01:21:47 -0500197 UNSUPPORTED("vkCmdBeginQuery::flags %d", int(flags));
Alexis Hetu86f8bdb2019-01-22 12:07:24 -0500198 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500199
200 pool[query].prepare(type);
201 pool[query].start();
202}
203
204void QueryPool::end(uint32_t query)
205{
206 ASSERT(query < count);
207 pool[query].finish();
208}
209
210void 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
221void 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 Clayton2ed93ab2019-12-17 20:38:03 +0000227 std::chrono::system_clock::now())
228 .time_since_epoch()
229 .count());
Nicolas Capens157ba262019-12-10 17:49:14 -0500230}
231
232} // namespace vk