blob: 6d9df5d760183a653c9b225236a91d6698395a43 [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;
Ian Ewell292f0052016-02-04 10:37:32 -050071 mStateManager->onBeginQuery(this);
72 return resume();
Geoff Langf9a6f082015-01-22 13:32:49 -050073}
74
75gl::Error QueryGL::end()
76{
Geoff Langf0aa8422015-09-29 15:08:34 -040077 return pause();
Geoff Langf9a6f082015-01-22 13:32:49 -050078}
79
Ian Ewell3ffd78b2016-01-22 16:09:42 -050080gl::Error QueryGL::queryCounter()
81{
82 ASSERT(mType == GL_TIMESTAMP);
83
84 // Directly create a query for the timestamp and add it to the pending query queue, as timestamp
85 // queries do not have the traditional begin/end block and never need to be paused/resumed
86 GLuint query;
87 mFunctions->genQueries(1, &query);
88 mFunctions->queryCounter(query, GL_TIMESTAMP);
89 mPendingQueries.push_back(query);
90
91 return gl::Error(GL_NO_ERROR);
92}
93
94template <typename T>
95gl::Error QueryGL::getResultBase(T *params)
Geoff Langf9a6f082015-01-22 13:32:49 -050096{
Geoff Langf0aa8422015-09-29 15:08:34 -040097 ASSERT(mActiveQuery == 0);
98
99 gl::Error error = flush(true);
100 if (error.isError())
101 {
102 return error;
103 }
104
105 ASSERT(mPendingQueries.empty());
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500106 *params = static_cast<T>(mResultSum);
Geoff Langf0aa8422015-09-29 15:08:34 -0400107
108 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500109}
110
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500111gl::Error QueryGL::getResult(GLint *params)
112{
113 return getResultBase(params);
114}
115
116gl::Error QueryGL::getResult(GLuint *params)
117{
118 return getResultBase(params);
119}
120
121gl::Error QueryGL::getResult(GLint64 *params)
122{
123 return getResultBase(params);
124}
125
126gl::Error QueryGL::getResult(GLuint64 *params)
127{
128 return getResultBase(params);
129}
130
131gl::Error QueryGL::isResultAvailable(bool *available)
Geoff Langf9a6f082015-01-22 13:32:49 -0500132{
Geoff Langf0aa8422015-09-29 15:08:34 -0400133 ASSERT(mActiveQuery == 0);
134
135 gl::Error error = flush(false);
136 if (error.isError())
137 {
138 return error;
139 }
140
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500141 *available = mPendingQueries.empty();
Geoff Langf0aa8422015-09-29 15:08:34 -0400142 return gl::Error(GL_NO_ERROR);
143}
144
145gl::Error QueryGL::pause()
146{
147 if (mActiveQuery != 0)
148 {
149 mStateManager->endQuery(mType, mActiveQuery);
150
151 mPendingQueries.push_back(mActiveQuery);
152 mActiveQuery = 0;
153 }
154
155 // Flush to make sure the pending queries don't add up too much.
156 gl::Error error = flush(false);
157 if (error.isError())
158 {
159 return error;
160 }
161
162 return gl::Error(GL_NO_ERROR);
163}
164
165gl::Error QueryGL::resume()
166{
167 if (mActiveQuery == 0)
168 {
169 // Flush to make sure the pending queries don't add up too much.
170 gl::Error error = flush(false);
171 if (error.isError())
172 {
173 return error;
174 }
175
176 mFunctions->genQueries(1, &mActiveQuery);
177 mStateManager->beginQuery(mType, mActiveQuery);
178 }
179
180 return gl::Error(GL_NO_ERROR);
181}
182
183gl::Error QueryGL::flush(bool force)
184{
185 while (!mPendingQueries.empty())
186 {
187 GLuint id = mPendingQueries.front();
188 if (!force)
189 {
190 GLuint resultAvailable = 0;
191 mFunctions->getQueryObjectuiv(id, GL_QUERY_RESULT_AVAILABLE, &resultAvailable);
192 if (resultAvailable == GL_FALSE)
193 {
194 return gl::Error(GL_NO_ERROR);
195 }
196 }
197
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500198 // Even though getQueryObjectui64v was introduced for timer queries, there is nothing in the
199 // standard that says that it doesn't work for any other queries. It also passes on all the
200 // trybots, so we use it if it is available
201 if (mFunctions->getQueryObjectui64v != nullptr)
202 {
203 GLuint64 result = 0;
204 mFunctions->getQueryObjectui64v(id, GL_QUERY_RESULT, &result);
205 mResultSum = MergeQueryResults(mType, mResultSum, result);
206 }
207 else
208 {
209 GLuint result = 0;
210 mFunctions->getQueryObjectuiv(id, GL_QUERY_RESULT, &result);
211 mResultSum = MergeQueryResults(mType, mResultSum, static_cast<GLuint64>(result));
212 }
Geoff Langf0aa8422015-09-29 15:08:34 -0400213
214 mStateManager->deleteQuery(id);
215
216 mPendingQueries.pop_front();
217 }
218
219 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500220}
221
222}