blob: 502b604e58217ea8e4830562ee5207222594193f [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
Geoff Langf0aa8422015-09-29 15:08:34 -040036 default:
37 UNREACHABLE();
38 return 0;
39 }
40}
41
42} // anonymous namespace
Geoff Langf9a6f082015-01-22 13:32:49 -050043
44namespace rx
45{
46
Geoff Langa20fc002016-08-08 15:19:56 -040047QueryGL::QueryGL(GLenum type) : QueryImpl(type)
48{
49}
50
51QueryGL::~QueryGL()
52{
53}
54
55StandardQueryGL::StandardQueryGL(GLenum type,
56 const FunctionsGL *functions,
57 StateManagerGL *stateManager)
58 : QueryGL(type),
Geoff Langf0aa8422015-09-29 15:08:34 -040059 mType(type),
60 mFunctions(functions),
61 mStateManager(stateManager),
62 mActiveQuery(0),
63 mPendingQueries(),
64 mResultSum(0)
65{
66}
Geoff Langf9a6f082015-01-22 13:32:49 -050067
Geoff Langa20fc002016-08-08 15:19:56 -040068StandardQueryGL::~StandardQueryGL()
Geoff Langf0aa8422015-09-29 15:08:34 -040069{
Geoff Langbcb4c682018-02-05 14:56:54 -050070 if (mActiveQuery != 0)
71 {
72 mStateManager->endQuery(mType, this, mActiveQuery);
73 mFunctions->deleteQueries(1, &mActiveQuery);
74 mActiveQuery = 0;
75 }
76
Geoff Langf0aa8422015-09-29 15:08:34 -040077 while (!mPendingQueries.empty())
78 {
Geoff Langbcb4c682018-02-05 14:56:54 -050079 GLuint id = mPendingQueries.front();
80 mFunctions->deleteQueries(1, &id);
Geoff Langf0aa8422015-09-29 15:08:34 -040081 mPendingQueries.pop_front();
82 }
83}
Geoff Langf9a6f082015-01-22 13:32:49 -050084
Geoff Langa20fc002016-08-08 15:19:56 -040085gl::Error StandardQueryGL::begin()
Geoff Langf9a6f082015-01-22 13:32:49 -050086{
Geoff Langf0aa8422015-09-29 15:08:34 -040087 mResultSum = 0;
Ian Ewell292f0052016-02-04 10:37:32 -050088 return resume();
Geoff Langf9a6f082015-01-22 13:32:49 -050089}
90
Geoff Langa20fc002016-08-08 15:19:56 -040091gl::Error StandardQueryGL::end()
Geoff Langf9a6f082015-01-22 13:32:49 -050092{
Geoff Langf0aa8422015-09-29 15:08:34 -040093 return pause();
Geoff Langf9a6f082015-01-22 13:32:49 -050094}
95
Geoff Langa20fc002016-08-08 15:19:56 -040096gl::Error StandardQueryGL::queryCounter()
Ian Ewell3ffd78b2016-01-22 16:09:42 -050097{
98 ASSERT(mType == GL_TIMESTAMP);
99
100 // Directly create a query for the timestamp and add it to the pending query queue, as timestamp
101 // queries do not have the traditional begin/end block and never need to be paused/resumed
102 GLuint query;
103 mFunctions->genQueries(1, &query);
104 mFunctions->queryCounter(query, GL_TIMESTAMP);
105 mPendingQueries.push_back(query);
106
He Yunchaoacd18982017-01-04 10:46:42 +0800107 return gl::NoError();
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500108}
109
110template <typename T>
Geoff Langa20fc002016-08-08 15:19:56 -0400111gl::Error StandardQueryGL::getResultBase(T *params)
Geoff Langf9a6f082015-01-22 13:32:49 -0500112{
Geoff Langf0aa8422015-09-29 15:08:34 -0400113 ASSERT(mActiveQuery == 0);
114
115 gl::Error error = flush(true);
116 if (error.isError())
117 {
118 return error;
119 }
120
121 ASSERT(mPendingQueries.empty());
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500122 *params = static_cast<T>(mResultSum);
Geoff Langf0aa8422015-09-29 15:08:34 -0400123
He Yunchaoacd18982017-01-04 10:46:42 +0800124 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500125}
126
Geoff Langa20fc002016-08-08 15:19:56 -0400127gl::Error StandardQueryGL::getResult(GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500128{
129 return getResultBase(params);
130}
131
Geoff Langa20fc002016-08-08 15:19:56 -0400132gl::Error StandardQueryGL::getResult(GLuint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500133{
134 return getResultBase(params);
135}
136
Geoff Langa20fc002016-08-08 15:19:56 -0400137gl::Error StandardQueryGL::getResult(GLint64 *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500138{
139 return getResultBase(params);
140}
141
Geoff Langa20fc002016-08-08 15:19:56 -0400142gl::Error StandardQueryGL::getResult(GLuint64 *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500143{
144 return getResultBase(params);
145}
146
Geoff Langa20fc002016-08-08 15:19:56 -0400147gl::Error StandardQueryGL::isResultAvailable(bool *available)
Geoff Langf9a6f082015-01-22 13:32:49 -0500148{
Geoff Langf0aa8422015-09-29 15:08:34 -0400149 ASSERT(mActiveQuery == 0);
150
151 gl::Error error = flush(false);
152 if (error.isError())
153 {
154 return error;
155 }
156
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500157 *available = mPendingQueries.empty();
He Yunchaoacd18982017-01-04 10:46:42 +0800158 return gl::NoError();
Geoff Langf0aa8422015-09-29 15:08:34 -0400159}
160
Geoff Langa20fc002016-08-08 15:19:56 -0400161gl::Error StandardQueryGL::pause()
Geoff Langf0aa8422015-09-29 15:08:34 -0400162{
163 if (mActiveQuery != 0)
164 {
Geoff Langbcb4c682018-02-05 14:56:54 -0500165 mStateManager->endQuery(mType, this, mActiveQuery);
Geoff Langf0aa8422015-09-29 15:08:34 -0400166
167 mPendingQueries.push_back(mActiveQuery);
168 mActiveQuery = 0;
169 }
170
171 // Flush to make sure the pending queries don't add up too much.
172 gl::Error error = flush(false);
173 if (error.isError())
174 {
175 return error;
176 }
177
He Yunchaoacd18982017-01-04 10:46:42 +0800178 return gl::NoError();
Geoff Langf0aa8422015-09-29 15:08:34 -0400179}
180
Geoff Langa20fc002016-08-08 15:19:56 -0400181gl::Error StandardQueryGL::resume()
Geoff Langf0aa8422015-09-29 15:08:34 -0400182{
183 if (mActiveQuery == 0)
184 {
185 // Flush to make sure the pending queries don't add up too much.
186 gl::Error error = flush(false);
187 if (error.isError())
188 {
189 return error;
190 }
191
192 mFunctions->genQueries(1, &mActiveQuery);
Geoff Langbcb4c682018-02-05 14:56:54 -0500193 mStateManager->beginQuery(mType, this, mActiveQuery);
Geoff Langf0aa8422015-09-29 15:08:34 -0400194 }
195
He Yunchaoacd18982017-01-04 10:46:42 +0800196 return gl::NoError();
Geoff Langf0aa8422015-09-29 15:08:34 -0400197}
198
Geoff Langa20fc002016-08-08 15:19:56 -0400199gl::Error StandardQueryGL::flush(bool force)
Geoff Langf0aa8422015-09-29 15:08:34 -0400200{
201 while (!mPendingQueries.empty())
202 {
203 GLuint id = mPendingQueries.front();
204 if (!force)
205 {
206 GLuint resultAvailable = 0;
207 mFunctions->getQueryObjectuiv(id, GL_QUERY_RESULT_AVAILABLE, &resultAvailable);
208 if (resultAvailable == GL_FALSE)
209 {
He Yunchaoacd18982017-01-04 10:46:42 +0800210 return gl::NoError();
Geoff Langf0aa8422015-09-29 15:08:34 -0400211 }
212 }
213
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500214 // Even though getQueryObjectui64v was introduced for timer queries, there is nothing in the
215 // standard that says that it doesn't work for any other queries. It also passes on all the
216 // trybots, so we use it if it is available
217 if (mFunctions->getQueryObjectui64v != nullptr)
218 {
219 GLuint64 result = 0;
220 mFunctions->getQueryObjectui64v(id, GL_QUERY_RESULT, &result);
221 mResultSum = MergeQueryResults(mType, mResultSum, result);
222 }
223 else
224 {
225 GLuint result = 0;
226 mFunctions->getQueryObjectuiv(id, GL_QUERY_RESULT, &result);
227 mResultSum = MergeQueryResults(mType, mResultSum, static_cast<GLuint64>(result));
228 }
Geoff Langf0aa8422015-09-29 15:08:34 -0400229
Geoff Langbcb4c682018-02-05 14:56:54 -0500230 mFunctions->deleteQueries(1, &id);
Geoff Langf0aa8422015-09-29 15:08:34 -0400231
232 mPendingQueries.pop_front();
233 }
234
He Yunchaoacd18982017-01-04 10:46:42 +0800235 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500236}
237
Geoff Langa20fc002016-08-08 15:19:56 -0400238class SyncProviderGL
239{
240 public:
241 virtual ~SyncProviderGL() {}
242 virtual gl::Error flush(bool force, bool *finished) = 0;
243};
244
245class SyncProviderGLSync : public SyncProviderGL
246{
247 public:
248 SyncProviderGLSync(const FunctionsGL *functions) : mFunctions(functions), mSync(nullptr)
249 {
250 mSync = mFunctions->fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
251 }
252
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500253 ~SyncProviderGLSync() override { mFunctions->deleteSync(mSync); }
Geoff Langa20fc002016-08-08 15:19:56 -0400254
255 gl::Error flush(bool force, bool *finished) override
256 {
257 if (force)
258 {
259 mFunctions->clientWaitSync(mSync, 0, 0);
260 *finished = true;
261 }
262 else
263 {
264 GLint value = 0;
265 mFunctions->getSynciv(mSync, GL_SYNC_STATUS, 1, nullptr, &value);
266 *finished = (value == GL_SIGNALED);
267 }
268
269 return gl::NoError();
270 }
271
272 private:
273 const FunctionsGL *mFunctions;
274 GLsync mSync;
275};
276
277class SyncProviderGLQuery : public SyncProviderGL
278{
279 public:
280 SyncProviderGLQuery(const FunctionsGL *functions,
281 StateManagerGL *stateManager,
282 GLenum queryType)
283 : mFunctions(functions), mQuery(0)
284 {
285 mFunctions->genQueries(1, &mQuery);
Jamie Madill71c88b32017-09-14 22:20:29 -0400286 ANGLE_SWALLOW_ERR(stateManager->pauseQuery(queryType));
Geoff Langa20fc002016-08-08 15:19:56 -0400287 mFunctions->beginQuery(queryType, mQuery);
288 mFunctions->endQuery(queryType);
Jamie Madill71c88b32017-09-14 22:20:29 -0400289 ANGLE_SWALLOW_ERR(stateManager->resumeQuery(queryType));
Geoff Langa20fc002016-08-08 15:19:56 -0400290 }
291
Jamie Madillacf2f3a2017-11-21 19:22:44 -0500292 ~SyncProviderGLQuery() override { mFunctions->deleteQueries(1, &mQuery); }
Geoff Langa20fc002016-08-08 15:19:56 -0400293
294 gl::Error flush(bool force, bool *finished) override
295 {
296 if (force)
297 {
298 GLint result = 0;
299 mFunctions->getQueryObjectiv(mQuery, GL_QUERY_RESULT, &result);
300 *finished = true;
301 }
302 else
303 {
304 GLint available = 0;
305 mFunctions->getQueryObjectiv(mQuery, GL_QUERY_RESULT_AVAILABLE, &available);
306 *finished = (available == GL_TRUE);
307 }
308
309 return gl::NoError();
310 }
311
312 private:
313 const FunctionsGL *mFunctions;
314 GLuint mQuery;
315};
316
317SyncQueryGL::SyncQueryGL(GLenum type, const FunctionsGL *functions, StateManagerGL *stateManager)
318 : QueryGL(type),
319 mFunctions(functions),
320 mStateManager(stateManager),
321 mSyncProvider(nullptr),
322 mFinished(false)
323{
324 ASSERT(IsSupported(mFunctions));
325 ASSERT(type == GL_COMMANDS_COMPLETED_CHROMIUM);
326}
327
328SyncQueryGL::~SyncQueryGL()
329{
330}
331
332bool SyncQueryGL::IsSupported(const FunctionsGL *functions)
333{
334 return nativegl::SupportsFenceSync(functions) || nativegl::SupportsOcclusionQueries(functions);
335}
336
337gl::Error SyncQueryGL::begin()
338{
339 return gl::NoError();
340}
341
342gl::Error SyncQueryGL::end()
343{
344 if (nativegl::SupportsFenceSync(mFunctions))
345 {
346 mSyncProvider.reset(new SyncProviderGLSync(mFunctions));
347 }
348 else if (nativegl::SupportsOcclusionQueries(mFunctions))
349 {
350 mSyncProvider.reset(
351 new SyncProviderGLQuery(mFunctions, mStateManager, GL_ANY_SAMPLES_PASSED));
352 }
353 else
354 {
355 ASSERT(false);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500356 return gl::InternalError() << "No native support for sync queries.";
Geoff Langa20fc002016-08-08 15:19:56 -0400357 }
358 return gl::NoError();
359}
360
361gl::Error SyncQueryGL::queryCounter()
362{
363 UNREACHABLE();
364 return gl::NoError();
365}
366
367gl::Error SyncQueryGL::getResult(GLint *params)
368{
369 return getResultBase(params);
370}
371
372gl::Error SyncQueryGL::getResult(GLuint *params)
373{
374 return getResultBase(params);
375}
376
377gl::Error SyncQueryGL::getResult(GLint64 *params)
378{
379 return getResultBase(params);
380}
381
382gl::Error SyncQueryGL::getResult(GLuint64 *params)
383{
384 return getResultBase(params);
385}
386
387gl::Error SyncQueryGL::isResultAvailable(bool *available)
388{
389 ANGLE_TRY(flush(false));
390 *available = mFinished;
391 return gl::NoError();
392}
393
394gl::Error SyncQueryGL::pause()
395{
396 return gl::NoError();
397}
398
399gl::Error SyncQueryGL::resume()
400{
401 return gl::NoError();
402}
403
404gl::Error SyncQueryGL::flush(bool force)
405{
406 if (mSyncProvider == nullptr)
407 {
408 ASSERT(mFinished);
409 return gl::NoError();
410 }
411
412 ANGLE_TRY(mSyncProvider->flush(force, &mFinished));
413 if (mFinished)
414 {
415 mSyncProvider.reset();
416 }
417
418 return gl::NoError();
419}
420
421template <typename T>
422gl::Error SyncQueryGL::getResultBase(T *params)
423{
424 ANGLE_TRY(flush(true));
425 *params = static_cast<T>(mFinished ? GL_TRUE : GL_FALSE);
426 return gl::NoError();
427}
Geoff Langf9a6f082015-01-22 13:32:49 -0500428}