1 /* Copyright (c) 2015-2021 The Khronos Group Inc.
2  * Copyright (c) 2015-2021 Valve Corporation
3  * Copyright (c) 2015-2021 LunarG, Inc.
4  * Copyright (C) 2015-2021 Google Inc.
5  * Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * Author: Courtney Goeltzenleuchter <courtneygo@google.com>
20  * Author: Tobin Ehlis <tobine@google.com>
21  * Author: Chris Forbes <chrisf@ijw.co.nz>
22  * Author: Mark Lobodzinski <mark@lunarg.com>
23  * Author: Dave Houlton <daveh@lunarg.com>
24  * Author: John Zulauf <jzulauf@lunarg.com>
25  * Author: Tobias Hector <tobias.hector@amd.com>
26  */
27 #pragma once
28 #include "base_node.h"
29 #include "hash_vk_types.h"
30 
31 enum QueryState {
32     QUERYSTATE_UNKNOWN,    // Initial state.
33     QUERYSTATE_RESET,      // After resetting.
34     QUERYSTATE_RUNNING,    // Query running.
35     QUERYSTATE_ENDED,      // Query ended but results may not be available.
36     QUERYSTATE_AVAILABLE,  // Results available.
37 };
38 
39 class QUERY_POOL_STATE : public BASE_NODE {
40   public:
QUERY_POOL_STATE(VkQueryPool qp,const VkQueryPoolCreateInfo * pCreateInfo,uint32_t index_count,uint32_t n_perf_pass,bool has_cb,bool has_rb)41     QUERY_POOL_STATE(VkQueryPool qp, const VkQueryPoolCreateInfo *pCreateInfo, uint32_t index_count, uint32_t n_perf_pass,
42                      bool has_cb, bool has_rb)
43         : BASE_NODE(qp, kVulkanObjectTypeQueryPool),
44           createInfo(*pCreateInfo),
45           has_perf_scope_command_buffer(has_cb),
46           has_perf_scope_render_pass(has_rb),
47           n_performance_passes(n_perf_pass),
48           perf_counter_index_count(index_count),
49           query_states_(pCreateInfo->queryCount) {
50         for (uint32_t i = 0; i < pCreateInfo->queryCount; ++i) {
51             auto perf_size = n_perf_pass > 0 ? n_perf_pass : 1;
52             query_states_[i].reserve(perf_size);
53             for (uint32_t p = 0; p < perf_size; p++) {
54                 query_states_[i].emplace_back(QUERYSTATE_UNKNOWN);
55             }
56         }
57     }
58 
pool()59     VkQueryPool pool() const { return handle_.Cast<VkQueryPool>(); }
60 
SetQueryState(uint32_t query,uint32_t perf_pass,QueryState state)61     void SetQueryState(uint32_t query, uint32_t perf_pass, QueryState state) {
62         assert(query < query_states_.size());
63         assert((n_performance_passes == 0 && perf_pass == 0) || (perf_pass < n_performance_passes));
64         query_states_[query][perf_pass] = state;
65     }
GetQueryState(uint32_t query,uint32_t perf_pass)66     QueryState GetQueryState(uint32_t query, uint32_t perf_pass) const {
67         assert(query < query_states_.size());
68         assert((n_performance_passes == 0 && perf_pass == 0) || (perf_pass < n_performance_passes));
69         return query_states_[query][perf_pass];
70     }
71 
72     const VkQueryPoolCreateInfo createInfo;
73 
74     const bool has_perf_scope_command_buffer;
75     const bool has_perf_scope_render_pass;
76     const uint32_t n_performance_passes;
77     const uint32_t perf_counter_index_count;
78 
79   private:
80     std::vector<small_vector<QueryState, 1>> query_states_;
81 };
82 
83 struct QueryObject {
84     VkQueryPool pool;
85     uint32_t query;
86     // These next two fields are *not* used in hash or comparison, they are effectively a data payload
87     uint32_t index;  // must be zero if !indexed
88     uint32_t perf_pass;
89     bool indexed;
90     // Command index in the command buffer where the end of the query was
91     // recorded (equal to the number of commands in the command buffer before
92     // the end of the query).
93     uint64_t endCommandIndex;
94 
QueryObjectQueryObject95     QueryObject(VkQueryPool pool_, uint32_t query_)
96         : pool(pool_), query(query_), index(0), perf_pass(0), indexed(false), endCommandIndex(0) {}
QueryObjectQueryObject97     QueryObject(VkQueryPool pool_, uint32_t query_, uint32_t index_)
98         : pool(pool_), query(query_), index(index_), perf_pass(0), indexed(true), endCommandIndex(0) {}
QueryObjectQueryObject99     QueryObject(const QueryObject &obj)
100         : pool(obj.pool),
101           query(obj.query),
102           index(obj.index),
103           perf_pass(obj.perf_pass),
104           indexed(obj.indexed),
105           endCommandIndex(obj.endCommandIndex) {}
QueryObjectQueryObject106     QueryObject(const QueryObject &obj, uint32_t perf_pass_)
107         : pool(obj.pool),
108           query(obj.query),
109           index(obj.index),
110           perf_pass(perf_pass_),
111           indexed(obj.indexed),
112           endCommandIndex(obj.endCommandIndex) {}
113     bool operator<(const QueryObject &rhs) const {
114         return (pool == rhs.pool) ? ((query == rhs.query) ? (perf_pass < rhs.perf_pass) : (query < rhs.query)) : pool < rhs.pool;
115     }
116 };
117 
118 inline bool operator==(const QueryObject &query1, const QueryObject &query2) {
119     return ((query1.pool == query2.pool) && (query1.query == query2.query) && (query1.perf_pass == query2.perf_pass));
120 }
121 
122 typedef std::map<QueryObject, QueryState> QueryMap;
123 
124 enum QueryResultType {
125     QUERYRESULT_UNKNOWN,
126     QUERYRESULT_NO_DATA,
127     QUERYRESULT_SOME_DATA,
128     QUERYRESULT_WAIT_ON_RESET,
129     QUERYRESULT_WAIT_ON_RUNNING,
130 };
131 
string_QueryResultType(QueryResultType result_type)132 inline const char *string_QueryResultType(QueryResultType result_type) {
133     switch (result_type) {
134         case QUERYRESULT_UNKNOWN:
135             return "query may be in an unknown state";
136         case QUERYRESULT_NO_DATA:
137             return "query may return no data";
138         case QUERYRESULT_SOME_DATA:
139             return "query will return some data or availability bit";
140         case QUERYRESULT_WAIT_ON_RESET:
141             return "waiting on a query that has been reset and not issued yet";
142         case QUERYRESULT_WAIT_ON_RUNNING:
143             return "waiting on a query that has not ended yet";
144     }
145     assert(false);
146     return "UNKNOWN QUERY STATE";  // Unreachable.
147 }
148 
149 namespace std {
150 template <>
151 struct hash<QueryObject> {
152     size_t operator()(QueryObject query) const throw() {
153         return hash<uint64_t>()((uint64_t)(query.pool)) ^
154                hash<uint64_t>()(static_cast<uint64_t>(query.query) | (static_cast<uint64_t>(query.perf_pass) << 32));
155     }
156 };
157 
158 }  // namespace std
159