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