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 #ifndef VK_QUERY_POOL_HPP_
16 #define VK_QUERY_POOL_HPP_
17 
18 #include "VkObject.hpp"
19 
20 #include "marl/event.h"
21 #include "marl/waitgroup.h"
22 
23 #include <atomic>
24 #include <condition_variable>
25 #include <mutex>
26 
27 namespace vk {
28 
29 class Query
30 {
31 public:
32 	static auto constexpr INVALID_TYPE = VK_QUERY_TYPE_MAX_ENUM;
33 
34 	Query();
35 
36 	enum State
37 	{
38 		UNAVAILABLE,
39 		ACTIVE,
40 		FINISHED
41 	};
42 
43 	struct Data
44 	{
45 		State state;    // The current query state.
46 		int64_t value;  // The current query value.
47 	};
48 
49 	// reset() sets the state of the Query to UNAVAILABLE, sets the type to
50 	// INVALID_TYPE and clears the query value.
51 	// reset() must not be called while the query is in the ACTIVE state.
52 	void reset();
53 
54 	// prepare() sets the Query type to ty, and sets the state to ACTIVE.
55 	// prepare() must not be called when the query is already ACTIVE.
56 	void prepare(VkQueryType ty);
57 
58 	// start() begins a query task which is closed with a call to finish().
59 	// Query tasks can be nested.
60 	// start() must only be called when in the ACTIVE state.
61 	void start();
62 
63 	// finish() ends a query task begun with a call to start().
64 	// Once all query tasks are complete the query will transition to the
65 	// FINISHED state.
66 	// finish() must only be called when in the ACTIVE state.
67 	void finish();
68 
69 	// wait() blocks until the query reaches the FINISHED state.
70 	void wait();
71 
72 	// getData() returns the current query state and value.
73 	Data getData() const;
74 
75 	// getType() returns the type of query.
76 	VkQueryType getType() const;
77 
78 	// set() replaces the current query value with val.
79 	void set(int64_t val);
80 
81 	// add() adds val to the current query value.
82 	void add(int64_t val);
83 
84 private:
85 	marl::WaitGroup wg;
86 	marl::Event finished;
87 	std::atomic<State> state;
88 	std::atomic<VkQueryType> type;
89 	std::atomic<int64_t> value;
90 };
91 
92 class QueryPool : public Object<QueryPool, VkQueryPool>
93 {
94 public:
95 	QueryPool(const VkQueryPoolCreateInfo *pCreateInfo, void *mem);
96 	void destroy(const VkAllocationCallbacks *pAllocator);
97 
98 	static size_t ComputeRequiredAllocationSize(const VkQueryPoolCreateInfo *pCreateInfo);
99 
100 	VkResult getResults(uint32_t firstQuery, uint32_t queryCount, size_t dataSize,
101 	                    void *pData, VkDeviceSize stride, VkQueryResultFlags flags) const;
102 	void begin(uint32_t query, VkQueryControlFlags flags);
103 	void end(uint32_t query);
104 	void reset(uint32_t firstQuery, uint32_t queryCount);
105 
106 	void writeTimestamp(uint32_t query);
107 
getQuery(uint32_t query) const108 	inline Query *getQuery(uint32_t query) const { return &(pool[query]); }
109 
110 private:
111 	Query *pool;
112 	VkQueryType type;
113 	uint32_t count;
114 };
115 
Cast(VkQueryPool object)116 static inline QueryPool *Cast(VkQueryPool object)
117 {
118 	return QueryPool::Cast(object);
119 }
120 
121 }  // namespace vk
122 
123 #endif  // VK_QUERY_POOL_HPP_
124