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