blob: 8e16fd2a4471b605f1d45502e7e33d76399d1e91 [file] [log] [blame]
Geoff Langf9a6f082015-01-22 13:32:49 -05001//
2// Copyright 2015 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// QueryGL.cpp: Implements the class methods for QueryGL.
8
9#include "libANGLE/renderer/gl/QueryGL.h"
10
11#include "common/debug.h"
Geoff Langf0aa8422015-09-29 15:08:34 -040012#include "libANGLE/renderer/gl/FunctionsGL.h"
13#include "libANGLE/renderer/gl/StateManagerGL.h"
14
15namespace
16{
17
Ian Ewell3ffd78b2016-01-22 16:09:42 -050018GLuint64 MergeQueryResults(GLenum type, GLuint64 currentResult, GLuint64 newResult)
Geoff Langf0aa8422015-09-29 15:08:34 -040019{
20 switch (type)
21 {
22 case GL_ANY_SAMPLES_PASSED:
23 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
24 return (currentResult == GL_TRUE || newResult == GL_TRUE) ? GL_TRUE : GL_FALSE;
25
26 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
27 return currentResult + newResult;
28
Ian Ewell3ffd78b2016-01-22 16:09:42 -050029 case GL_TIME_ELAPSED:
30 return currentResult + newResult;
31
32 case GL_TIMESTAMP:
33 return newResult;
34
Geoff Langf0aa8422015-09-29 15:08:34 -040035 default:
36 UNREACHABLE();
37 return 0;
38 }
39}
40
41} // anonymous namespace
Geoff Langf9a6f082015-01-22 13:32:49 -050042
43namespace rx
44{
45
Geoff Langf0aa8422015-09-29 15:08:34 -040046QueryGL::QueryGL(GLenum type, const FunctionsGL *functions, StateManagerGL *stateManager)
47 : QueryImpl(type),
48 mType(type),
49 mFunctions(functions),
50 mStateManager(stateManager),
51 mActiveQuery(0),
52 mPendingQueries(),
53 mResultSum(0)
54{
55}
Geoff Langf9a6f082015-01-22 13:32:49 -050056
57QueryGL::~QueryGL()
Geoff Langf0aa8422015-09-29 15:08:34 -040058{
59 mStateManager->deleteQuery(mActiveQuery);
60 mStateManager->onDeleteQueryObject(this);
61 while (!mPendingQueries.empty())
62 {
63 mStateManager->deleteQuery(mPendingQueries.front());
64 mPendingQueries.pop_front();
65 }
66}
Geoff Langf9a6f082015-01-22 13:32:49 -050067
68gl::Error QueryGL::begin()
69{
Geoff Langf0aa8422015-09-29 15:08:34 -040070 mResultSum = 0;
71 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -050072}
73
74gl::Error QueryGL::end()
75{
Geoff Langf0aa8422015-09-29 15:08:34 -040076 return pause();
Geoff Langf9a6f082015-01-22 13:32:49 -050077}
78
Ian Ewell3ffd78b2016-01-22 16:09:42 -050079gl::Error QueryGL::queryCounter()
80{
81 ASSERT(mType == GL_TIMESTAMP);
82
83 // Directly create a query for the timestamp and add it to the pending query queue, as timestamp
84 // queries do not have the traditional begin/end block and never need to be paused/resumed
85 GLuint query;
86 mFunctions->genQueries(1, &query);
87 mFunctions->queryCounter(query, GL_TIMESTAMP);
88 mPendingQueries.push_back(query);
89
90 return gl::Error(GL_NO_ERROR);
91}
92
93template <typename T>
94gl::Error QueryGL::getResultBase(T *params)
Geoff Langf9a6f082015-01-22 13:32:49 -050095{
Geoff Langf0aa8422015-09-29 15:08:34 -040096 ASSERT(mActiveQuery == 0);
97
98 gl::Error error = flush(true);
99 if (error.isError())
100 {
101 return error;
102 }
103
104 ASSERT(mPendingQueries.empty());
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500105 *params = static_cast<T>(mResultSum);
Geoff Langf0aa8422015-09-29 15:08:34 -0400106
107 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500108}
109
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500110gl::Error QueryGL::getResult(GLint *params)
111{
112 return getResultBase(params);
113}
114
115gl::Error QueryGL::getResult(GLuint *params)
116{
117 return getResultBase(params);
118}
119
120gl::Error QueryGL::getResult(GLint64 *params)
121{
122 return getResultBase(params);
123}
124
125gl::Error QueryGL::getResult(GLuint64 *params)
126{
127 return getResultBase(params);
128}
129
130gl::Error QueryGL::isResultAvailable(bool *available)
Geoff Langf9a6f082015-01-22 13:32:49 -0500131{
Geoff Langf0aa8422015-09-29 15:08:34 -0400132 ASSERT(mActiveQuery == 0);
133
134 gl::Error error = flush(false);
135 if (error.isError())
136 {
137 return error;
138 }
139
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500140 *available = mPendingQueries.empty();
Geoff Langf0aa8422015-09-29 15:08:34 -0400141 return gl::Error(GL_NO_ERROR);
142}
143
144gl::Error QueryGL::pause()
145{
146 if (mActiveQuery != 0)
147 {
148 mStateManager->endQuery(mType, mActiveQuery);
149
150 mPendingQueries.push_back(mActiveQuery);
151 mActiveQuery = 0;
152 }
153
154 // Flush to make sure the pending queries don't add up too much.
155 gl::Error error = flush(false);
156 if (error.isError())
157 {
158 return error;
159 }
160
161 return gl::Error(GL_NO_ERROR);
162}
163
164gl::Error QueryGL::resume()
165{
166 if (mActiveQuery == 0)
167 {
168 // Flush to make sure the pending queries don't add up too much.
169 gl::Error error = flush(false);
170 if (error.isError())
171 {
172 return error;
173 }
174
175 mFunctions->genQueries(1, &mActiveQuery);
176 mStateManager->beginQuery(mType, mActiveQuery);
177 }
178
179 return gl::Error(GL_NO_ERROR);
180}
181
182gl::Error QueryGL::flush(bool force)
183{
184 while (!mPendingQueries.empty())
185 {
186 GLuint id = mPendingQueries.front();
187 if (!force)
188 {
189 GLuint resultAvailable = 0;
190 mFunctions->getQueryObjectuiv(id, GL_QUERY_RESULT_AVAILABLE, &resultAvailable);
191 if (resultAvailable == GL_FALSE)
192 {
193 return gl::Error(GL_NO_ERROR);
194 }
195 }
196
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500197 // Even though getQueryObjectui64v was introduced for timer queries, there is nothing in the
198 // standard that says that it doesn't work for any other queries. It also passes on all the
199 // trybots, so we use it if it is available
200 if (mFunctions->getQueryObjectui64v != nullptr)
201 {
202 GLuint64 result = 0;
203 mFunctions->getQueryObjectui64v(id, GL_QUERY_RESULT, &result);
204 mResultSum = MergeQueryResults(mType, mResultSum, result);
205 }
206 else
207 {
208 GLuint result = 0;
209 mFunctions->getQueryObjectuiv(id, GL_QUERY_RESULT, &result);
210 mResultSum = MergeQueryResults(mType, mResultSum, static_cast<GLuint64>(result));
211 }
Geoff Langf0aa8422015-09-29 15:08:34 -0400212
213 mStateManager->deleteQuery(id);
214
215 mPendingQueries.pop_front();
216 }
217
218 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500219}
220
221}