blob: 449f819a728ebae8c9736408fb5cf0b58569fe2a [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
Corentin Wallezad3ae902018-03-09 13:40:42 -050019GLuint64 MergeQueryResults(gl::QueryType type, GLuint64 currentResult, GLuint64 newResult)
Geoff Langf0aa8422015-09-29 15:08:34 -040020{
21 switch (type)
22 {
Corentin Wallezad3ae902018-03-09 13:40:42 -050023 case gl::QueryType::AnySamples:
24 case gl::QueryType::AnySamplesConservative:
Geoff Langf0aa8422015-09-29 15:08:34 -040025 return (currentResult == GL_TRUE || newResult == GL_TRUE) ? GL_TRUE : GL_FALSE;
26
Corentin Wallezad3ae902018-03-09 13:40:42 -050027 case gl::QueryType::TransformFeedbackPrimitivesWritten:
Geoff Langf0aa8422015-09-29 15:08:34 -040028 return currentResult + newResult;
29
Corentin Wallezad3ae902018-03-09 13:40:42 -050030 case gl::QueryType::TimeElapsed:
Ian Ewell3ffd78b2016-01-22 16:09:42 -050031 return currentResult + newResult;
32
Corentin Wallezad3ae902018-03-09 13:40:42 -050033 case gl::QueryType::Timestamp:
Ian Ewell3ffd78b2016-01-22 16:09:42 -050034 return newResult;
35
Corentin Wallezad3ae902018-03-09 13:40:42 -050036 case gl::QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +080037 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
Corentin Wallezad3ae902018-03-09 13:40:42 -050050QueryGL::QueryGL(gl::QueryType type) : QueryImpl(type)
Geoff Langa20fc002016-08-08 15:19:56 -040051{
52}
53
54QueryGL::~QueryGL()
55{
56}
57
Corentin Wallezad3ae902018-03-09 13:40:42 -050058StandardQueryGL::StandardQueryGL(gl::QueryType type,
Geoff Langa20fc002016-08-08 15:19:56 -040059 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{
Corentin Wallezad3ae902018-03-09 13:40:42 -0500101 ASSERT(mType == gl::QueryType::Timestamp);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500102
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,
Corentin Wallezad3ae902018-03-09 13:40:42 -0500285 gl::QueryType type)
Geoff Langa20fc002016-08-08 15:19:56 -0400286 : mFunctions(functions), mQuery(0)
287 {
288 mFunctions->genQueries(1, &mQuery);
Corentin Wallezad3ae902018-03-09 13:40:42 -0500289 ANGLE_SWALLOW_ERR(stateManager->pauseQuery(type));
290 mFunctions->beginQuery(ToGLenum(type), mQuery);
291 mFunctions->endQuery(ToGLenum(type));
292 ANGLE_SWALLOW_ERR(stateManager->resumeQuery(type));
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
Corentin Wallezad3ae902018-03-09 13:40:42 -0500320SyncQueryGL::SyncQueryGL(gl::QueryType type,
321 const FunctionsGL *functions,
322 StateManagerGL *stateManager)
Geoff Langa20fc002016-08-08 15:19:56 -0400323 : QueryGL(type),
324 mFunctions(functions),
325 mStateManager(stateManager),
326 mSyncProvider(nullptr),
327 mFinished(false)
328{
329 ASSERT(IsSupported(mFunctions));
Corentin Wallezad3ae902018-03-09 13:40:42 -0500330 ASSERT(type == gl::QueryType::CommandsCompleted);
Geoff Langa20fc002016-08-08 15:19:56 -0400331}
332
333SyncQueryGL::~SyncQueryGL()
334{
335}
336
337bool SyncQueryGL::IsSupported(const FunctionsGL *functions)
338{
339 return nativegl::SupportsFenceSync(functions) || nativegl::SupportsOcclusionQueries(functions);
340}
341
342gl::Error SyncQueryGL::begin()
343{
344 return gl::NoError();
345}
346
347gl::Error SyncQueryGL::end()
348{
349 if (nativegl::SupportsFenceSync(mFunctions))
350 {
351 mSyncProvider.reset(new SyncProviderGLSync(mFunctions));
352 }
353 else if (nativegl::SupportsOcclusionQueries(mFunctions))
354 {
355 mSyncProvider.reset(
Corentin Wallezad3ae902018-03-09 13:40:42 -0500356 new SyncProviderGLQuery(mFunctions, mStateManager, gl::QueryType::AnySamples));
Geoff Langa20fc002016-08-08 15:19:56 -0400357 }
358 else
359 {
360 ASSERT(false);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500361 return gl::InternalError() << "No native support for sync queries.";
Geoff Langa20fc002016-08-08 15:19:56 -0400362 }
363 return gl::NoError();
364}
365
366gl::Error SyncQueryGL::queryCounter()
367{
368 UNREACHABLE();
369 return gl::NoError();
370}
371
372gl::Error SyncQueryGL::getResult(GLint *params)
373{
374 return getResultBase(params);
375}
376
377gl::Error SyncQueryGL::getResult(GLuint *params)
378{
379 return getResultBase(params);
380}
381
382gl::Error SyncQueryGL::getResult(GLint64 *params)
383{
384 return getResultBase(params);
385}
386
387gl::Error SyncQueryGL::getResult(GLuint64 *params)
388{
389 return getResultBase(params);
390}
391
392gl::Error SyncQueryGL::isResultAvailable(bool *available)
393{
394 ANGLE_TRY(flush(false));
395 *available = mFinished;
396 return gl::NoError();
397}
398
399gl::Error SyncQueryGL::pause()
400{
401 return gl::NoError();
402}
403
404gl::Error SyncQueryGL::resume()
405{
406 return gl::NoError();
407}
408
409gl::Error SyncQueryGL::flush(bool force)
410{
411 if (mSyncProvider == nullptr)
412 {
413 ASSERT(mFinished);
414 return gl::NoError();
415 }
416
417 ANGLE_TRY(mSyncProvider->flush(force, &mFinished));
418 if (mFinished)
419 {
420 mSyncProvider.reset();
421 }
422
423 return gl::NoError();
424}
425
426template <typename T>
427gl::Error SyncQueryGL::getResultBase(T *params)
428{
429 ANGLE_TRY(flush(true));
430 *params = static_cast<T>(mFinished ? GL_TRUE : GL_FALSE);
431 return gl::NoError();
432}
Geoff Langf9a6f082015-01-22 13:32:49 -0500433}