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