blob: 9126c86e88ab314a820547bd06924ed277ee0de3 [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"
Geoff Langa20fc002016-08-08 15:19:56 -040014#include "libANGLE/renderer/gl/renderergl_utils.h"
Geoff Langf0aa8422015-09-29 15:08:34 -040015
16namespace
17{
18
Ian Ewell3ffd78b2016-01-22 16:09:42 -050019GLuint64 MergeQueryResults(GLenum type, GLuint64 currentResult, GLuint64 newResult)
Geoff Langf0aa8422015-09-29 15:08:34 -040020{
21 switch (type)
22 {
23 case GL_ANY_SAMPLES_PASSED:
24 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
25 return (currentResult == GL_TRUE || newResult == GL_TRUE) ? GL_TRUE : GL_FALSE;
26
27 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
28 return currentResult + newResult;
29
Ian Ewell3ffd78b2016-01-22 16:09:42 -050030 case GL_TIME_ELAPSED:
31 return currentResult + newResult;
32
33 case GL_TIMESTAMP:
34 return newResult;
35
Jiawei Shaod2fa07e2018-03-15 09:20:25 +080036 case GL_PRIMITIVES_GENERATED_EXT:
37 return currentResult + newResult;
38
Geoff Langf0aa8422015-09-29 15:08:34 -040039 default:
40 UNREACHABLE();
41 return 0;
42 }
43}
44
45} // anonymous namespace
Geoff Langf9a6f082015-01-22 13:32:49 -050046
47namespace rx
48{
49
Geoff Langa20fc002016-08-08 15:19:56 -040050QueryGL::QueryGL(GLenum type) : QueryImpl(type)
51{
52}
53
54QueryGL::~QueryGL()
55{
56}
57
58StandardQueryGL::StandardQueryGL(GLenum type,
59 const FunctionsGL *functions,
60 StateManagerGL *stateManager)
61 : QueryGL(type),
Geoff Langf0aa8422015-09-29 15:08:34 -040062 mType(type),
63 mFunctions(functions),
64 mStateManager(stateManager),
65 mActiveQuery(0),
66 mPendingQueries(),
67 mResultSum(0)
68{
69}
Geoff Langf9a6f082015-01-22 13:32:49 -050070
Geoff Langa20fc002016-08-08 15:19:56 -040071StandardQueryGL::~StandardQueryGL()
Geoff Langf0aa8422015-09-29 15:08:34 -040072{
Geoff Langbcb4c682018-02-05 14:56:54 -050073 if (mActiveQuery != 0)
74 {
75 mStateManager->endQuery(mType, this, mActiveQuery);
76 mFunctions->deleteQueries(1, &mActiveQuery);
77 mActiveQuery = 0;
78 }
79
Geoff Langf0aa8422015-09-29 15:08:34 -040080 while (!mPendingQueries.empty())
81 {
Geoff Langbcb4c682018-02-05 14:56:54 -050082 GLuint id = mPendingQueries.front();
83 mFunctions->deleteQueries(1, &id);
Geoff Langf0aa8422015-09-29 15:08:34 -040084 mPendingQueries.pop_front();
85 }
86}
Geoff Langf9a6f082015-01-22 13:32:49 -050087
Geoff Langa20fc002016-08-08 15:19:56 -040088gl::Error StandardQueryGL::begin()
Geoff Langf9a6f082015-01-22 13:32:49 -050089{
Geoff Langf0aa8422015-09-29 15:08:34 -040090 mResultSum = 0;
Ian Ewell292f0052016-02-04 10:37:32 -050091 return resume();
Geoff Langf9a6f082015-01-22 13:32:49 -050092}
93
Geoff Langa20fc002016-08-08 15:19:56 -040094gl::Error StandardQueryGL::end()
Geoff Langf9a6f082015-01-22 13:32:49 -050095{
Geoff Langf0aa8422015-09-29 15:08:34 -040096 return pause();
Geoff Langf9a6f082015-01-22 13:32:49 -050097}
98
Geoff Langa20fc002016-08-08 15:19:56 -040099gl::Error StandardQueryGL::queryCounter()
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500100{
101 ASSERT(mType == GL_TIMESTAMP);
102
103 // Directly create a query for the timestamp and add it to the pending query queue, as timestamp
104 // queries do not have the traditional begin/end block and never need to be paused/resumed
105 GLuint query;
106 mFunctions->genQueries(1, &query);
107 mFunctions->queryCounter(query, GL_TIMESTAMP);
108 mPendingQueries.push_back(query);
109
He Yunchaoacd18982017-01-04 10:46:42 +0800110 return gl::NoError();
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500111}
112
113template <typename T>
Geoff Langa20fc002016-08-08 15:19:56 -0400114gl::Error StandardQueryGL::getResultBase(T *params)
Geoff Langf9a6f082015-01-22 13:32:49 -0500115{
Geoff Langf0aa8422015-09-29 15:08:34 -0400116 ASSERT(mActiveQuery == 0);
117
118 gl::Error error = flush(true);
119 if (error.isError())
120 {
121 return error;
122 }
123
124 ASSERT(mPendingQueries.empty());
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500125 *params = static_cast<T>(mResultSum);
Geoff Langf0aa8422015-09-29 15:08:34 -0400126
He Yunchaoacd18982017-01-04 10:46:42 +0800127 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500128}
129
Geoff Langa20fc002016-08-08 15:19:56 -0400130gl::Error StandardQueryGL::getResult(GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500131{
132 return getResultBase(params);
133}
134
Geoff Langa20fc002016-08-08 15:19:56 -0400135gl::Error StandardQueryGL::getResult(GLuint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500136{
137 return getResultBase(params);
138}
139
Geoff Langa20fc002016-08-08 15:19:56 -0400140gl::Error StandardQueryGL::getResult(GLint64 *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500141{
142 return getResultBase(params);
143}
144
Geoff Langa20fc002016-08-08 15:19:56 -0400145gl::Error StandardQueryGL::getResult(GLuint64 *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500146{
147 return getResultBase(params);
148}
149
Geoff Langa20fc002016-08-08 15:19:56 -0400150gl::Error StandardQueryGL::isResultAvailable(bool *available)
Geoff Langf9a6f082015-01-22 13:32:49 -0500151{
Geoff Langf0aa8422015-09-29 15:08:34 -0400152 ASSERT(mActiveQuery == 0);
153
154 gl::Error error = flush(false);
155 if (error.isError())
156 {
157 return error;
158 }
159
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500160 *available = mPendingQueries.empty();
He Yunchaoacd18982017-01-04 10:46:42 +0800161 return gl::NoError();
Geoff Langf0aa8422015-09-29 15:08:34 -0400162}
163
Geoff Langa20fc002016-08-08 15:19:56 -0400164gl::Error StandardQueryGL::pause()
Geoff Langf0aa8422015-09-29 15:08:34 -0400165{
166 if (mActiveQuery != 0)
167 {
Geoff Langbcb4c682018-02-05 14:56:54 -0500168 mStateManager->endQuery(mType, this, mActiveQuery);
Geoff Langf0aa8422015-09-29 15:08:34 -0400169
170 mPendingQueries.push_back(mActiveQuery);
171 mActiveQuery = 0;
172 }
173
174 // Flush to make sure the pending queries don't add up too much.
175 gl::Error error = flush(false);
176 if (error.isError())
177 {
178 return error;
179 }
180
He Yunchaoacd18982017-01-04 10:46:42 +0800181 return gl::NoError();
Geoff Langf0aa8422015-09-29 15:08:34 -0400182}
183
Geoff Langa20fc002016-08-08 15:19:56 -0400184gl::Error StandardQueryGL::resume()
Geoff Langf0aa8422015-09-29 15:08:34 -0400185{
186 if (mActiveQuery == 0)
187 {
188 // Flush to make sure the pending queries don't add up too much.
189 gl::Error error = flush(false);
190 if (error.isError())
191 {
192 return error;
193 }
194
195 mFunctions->genQueries(1, &mActiveQuery);
Geoff Langbcb4c682018-02-05 14:56:54 -0500196 mStateManager->beginQuery(mType, this, mActiveQuery);
Geoff Langf0aa8422015-09-29 15:08:34 -0400197 }
198
He Yunchaoacd18982017-01-04 10:46:42 +0800199 return gl::NoError();
Geoff Langf0aa8422015-09-29 15:08:34 -0400200}
201
Geoff Langa20fc002016-08-08 15:19:56 -0400202gl::Error StandardQueryGL::flush(bool force)
Geoff Langf0aa8422015-09-29 15:08:34 -0400203{
204 while (!mPendingQueries.empty())
205 {
206 GLuint id = mPendingQueries.front();
207 if (!force)
208 {
209 GLuint resultAvailable = 0;
210 mFunctions->getQueryObjectuiv(id, GL_QUERY_RESULT_AVAILABLE, &resultAvailable);
211 if (resultAvailable == GL_FALSE)
212 {
He Yunchaoacd18982017-01-04 10:46:42 +0800213 return gl::NoError();
Geoff Langf0aa8422015-09-29 15:08:34 -0400214 }
215 }
216
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500217 // Even though getQueryObjectui64v was introduced for timer queries, there is nothing in the
218 // standard that says that it doesn't work for any other queries. It also passes on all the
219 // trybots, so we use it if it is available
220 if (mFunctions->getQueryObjectui64v != nullptr)
221 {
222 GLuint64 result = 0;
223 mFunctions->getQueryObjectui64v(id, GL_QUERY_RESULT, &result);
224 mResultSum = MergeQueryResults(mType, mResultSum, result);
225 }
226 else
227 {
228 GLuint result = 0;
229 mFunctions->getQueryObjectuiv(id, GL_QUERY_RESULT, &result);
230 mResultSum = MergeQueryResults(mType, mResultSum, static_cast<GLuint64>(result));
231 }
Geoff Langf0aa8422015-09-29 15:08:34 -0400232
Geoff Langbcb4c682018-02-05 14:56:54 -0500233 mFunctions->deleteQueries(1, &id);
Geoff Langf0aa8422015-09-29 15:08:34 -0400234
235 mPendingQueries.pop_front();
236 }
237
He Yunchaoacd18982017-01-04 10:46:42 +0800238 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500239}
240
Geoff Langa20fc002016-08-08 15:19:56 -0400241class SyncProviderGL
242{
243 public:
244 virtual ~SyncProviderGL() {}
245 virtual gl::Error flush(bool force, bool *finished) = 0;
246};
247
248class SyncProviderGLSync : public SyncProviderGL
249{
250 public:
251 SyncProviderGLSync(const FunctionsGL *functions) : mFunctions(functions), mSync(nullptr)
252 {
253 mSync = mFunctions->fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
254 }
255
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500256 ~SyncProviderGLSync() override { mFunctions->deleteSync(mSync); }
Geoff Langa20fc002016-08-08 15:19:56 -0400257
258 gl::Error flush(bool force, bool *finished) override
259 {
260 if (force)
261 {
262 mFunctions->clientWaitSync(mSync, 0, 0);
263 *finished = true;
264 }
265 else
266 {
267 GLint value = 0;
268 mFunctions->getSynciv(mSync, GL_SYNC_STATUS, 1, nullptr, &value);
269 *finished = (value == GL_SIGNALED);
270 }
271
272 return gl::NoError();
273 }
274
275 private:
276 const FunctionsGL *mFunctions;
277 GLsync mSync;
278};
279
280class SyncProviderGLQuery : public SyncProviderGL
281{
282 public:
283 SyncProviderGLQuery(const FunctionsGL *functions,
284 StateManagerGL *stateManager,
285 GLenum queryType)
286 : mFunctions(functions), mQuery(0)
287 {
288 mFunctions->genQueries(1, &mQuery);
Jamie Madill71c88b32017-09-14 22:20:29 -0400289 ANGLE_SWALLOW_ERR(stateManager->pauseQuery(queryType));
Geoff Langa20fc002016-08-08 15:19:56 -0400290 mFunctions->beginQuery(queryType, mQuery);
291 mFunctions->endQuery(queryType);
Jamie Madill71c88b32017-09-14 22:20:29 -0400292 ANGLE_SWALLOW_ERR(stateManager->resumeQuery(queryType));
Geoff Langa20fc002016-08-08 15:19:56 -0400293 }
294
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500295 ~SyncProviderGLQuery() override { mFunctions->deleteQueries(1, &mQuery); }
Geoff Langa20fc002016-08-08 15:19:56 -0400296
297 gl::Error flush(bool force, bool *finished) override
298 {
299 if (force)
300 {
301 GLint result = 0;
302 mFunctions->getQueryObjectiv(mQuery, GL_QUERY_RESULT, &result);
303 *finished = true;
304 }
305 else
306 {
307 GLint available = 0;
308 mFunctions->getQueryObjectiv(mQuery, GL_QUERY_RESULT_AVAILABLE, &available);
309 *finished = (available == GL_TRUE);
310 }
311
312 return gl::NoError();
313 }
314
315 private:
316 const FunctionsGL *mFunctions;
317 GLuint mQuery;
318};
319
320SyncQueryGL::SyncQueryGL(GLenum type, const FunctionsGL *functions, StateManagerGL *stateManager)
321 : QueryGL(type),
322 mFunctions(functions),
323 mStateManager(stateManager),
324 mSyncProvider(nullptr),
325 mFinished(false)
326{
327 ASSERT(IsSupported(mFunctions));
328 ASSERT(type == GL_COMMANDS_COMPLETED_CHROMIUM);
329}
330
331SyncQueryGL::~SyncQueryGL()
332{
333}
334
335bool SyncQueryGL::IsSupported(const FunctionsGL *functions)
336{
337 return nativegl::SupportsFenceSync(functions) || nativegl::SupportsOcclusionQueries(functions);
338}
339
340gl::Error SyncQueryGL::begin()
341{
342 return gl::NoError();
343}
344
345gl::Error SyncQueryGL::end()
346{
347 if (nativegl::SupportsFenceSync(mFunctions))
348 {
349 mSyncProvider.reset(new SyncProviderGLSync(mFunctions));
350 }
351 else if (nativegl::SupportsOcclusionQueries(mFunctions))
352 {
353 mSyncProvider.reset(
354 new SyncProviderGLQuery(mFunctions, mStateManager, GL_ANY_SAMPLES_PASSED));
355 }
356 else
357 {
358 ASSERT(false);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500359 return gl::InternalError() << "No native support for sync queries.";
Geoff Langa20fc002016-08-08 15:19:56 -0400360 }
361 return gl::NoError();
362}
363
364gl::Error SyncQueryGL::queryCounter()
365{
366 UNREACHABLE();
367 return gl::NoError();
368}
369
370gl::Error SyncQueryGL::getResult(GLint *params)
371{
372 return getResultBase(params);
373}
374
375gl::Error SyncQueryGL::getResult(GLuint *params)
376{
377 return getResultBase(params);
378}
379
380gl::Error SyncQueryGL::getResult(GLint64 *params)
381{
382 return getResultBase(params);
383}
384
385gl::Error SyncQueryGL::getResult(GLuint64 *params)
386{
387 return getResultBase(params);
388}
389
390gl::Error SyncQueryGL::isResultAvailable(bool *available)
391{
392 ANGLE_TRY(flush(false));
393 *available = mFinished;
394 return gl::NoError();
395}
396
397gl::Error SyncQueryGL::pause()
398{
399 return gl::NoError();
400}
401
402gl::Error SyncQueryGL::resume()
403{
404 return gl::NoError();
405}
406
407gl::Error SyncQueryGL::flush(bool force)
408{
409 if (mSyncProvider == nullptr)
410 {
411 ASSERT(mFinished);
412 return gl::NoError();
413 }
414
415 ANGLE_TRY(mSyncProvider->flush(force, &mFinished));
416 if (mFinished)
417 {
418 mSyncProvider.reset();
419 }
420
421 return gl::NoError();
422}
423
424template <typename T>
425gl::Error SyncQueryGL::getResultBase(T *params)
426{
427 ANGLE_TRY(flush(true));
428 *params = static_cast<T>(mFinished ? GL_TRUE : GL_FALSE);
429 return gl::NoError();
430}
Geoff Langf9a6f082015-01-22 13:32:49 -0500431}