xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/gl/QueryGL.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker 
7*8975f5c5SAndroid Build Coastguard Worker // QueryGL.cpp: Implements the class methods for QueryGL.
8*8975f5c5SAndroid Build Coastguard Worker 
9*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/gl/QueryGL.h"
10*8975f5c5SAndroid Build Coastguard Worker 
11*8975f5c5SAndroid Build Coastguard Worker #include "common/debug.h"
12*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/gl/ContextGL.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/gl/FunctionsGL.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/gl/StateManagerGL.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/gl/renderergl_utils.h"
17*8975f5c5SAndroid Build Coastguard Worker 
18*8975f5c5SAndroid Build Coastguard Worker namespace
19*8975f5c5SAndroid Build Coastguard Worker {
20*8975f5c5SAndroid Build Coastguard Worker 
MergeQueryResults(gl::QueryType type,GLuint64 currentResult,GLuint64 newResult)21*8975f5c5SAndroid Build Coastguard Worker GLuint64 MergeQueryResults(gl::QueryType type, GLuint64 currentResult, GLuint64 newResult)
22*8975f5c5SAndroid Build Coastguard Worker {
23*8975f5c5SAndroid Build Coastguard Worker     switch (type)
24*8975f5c5SAndroid Build Coastguard Worker     {
25*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::AnySamples:
26*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::AnySamplesConservative:
27*8975f5c5SAndroid Build Coastguard Worker             return (currentResult == GL_TRUE || newResult == GL_TRUE) ? GL_TRUE : GL_FALSE;
28*8975f5c5SAndroid Build Coastguard Worker 
29*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::TransformFeedbackPrimitivesWritten:
30*8975f5c5SAndroid Build Coastguard Worker             return currentResult + newResult;
31*8975f5c5SAndroid Build Coastguard Worker 
32*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::TimeElapsed:
33*8975f5c5SAndroid Build Coastguard Worker             return currentResult + newResult;
34*8975f5c5SAndroid Build Coastguard Worker 
35*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::Timestamp:
36*8975f5c5SAndroid Build Coastguard Worker             return newResult;
37*8975f5c5SAndroid Build Coastguard Worker 
38*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::PrimitivesGenerated:
39*8975f5c5SAndroid Build Coastguard Worker             return currentResult + newResult;
40*8975f5c5SAndroid Build Coastguard Worker 
41*8975f5c5SAndroid Build Coastguard Worker         default:
42*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
43*8975f5c5SAndroid Build Coastguard Worker             return 0;
44*8975f5c5SAndroid Build Coastguard Worker     }
45*8975f5c5SAndroid Build Coastguard Worker }
46*8975f5c5SAndroid Build Coastguard Worker 
47*8975f5c5SAndroid Build Coastguard Worker // Some drivers tend to hang when flushing pending queries.  Wait until this number of queries have
48*8975f5c5SAndroid Build Coastguard Worker // added up before checking if results are ready.
49*8975f5c5SAndroid Build Coastguard Worker constexpr uint32_t kPauseResumeFlushThreshold = 5;
50*8975f5c5SAndroid Build Coastguard Worker }  // anonymous namespace
51*8975f5c5SAndroid Build Coastguard Worker 
52*8975f5c5SAndroid Build Coastguard Worker namespace rx
53*8975f5c5SAndroid Build Coastguard Worker {
54*8975f5c5SAndroid Build Coastguard Worker 
QueryGL(gl::QueryType type)55*8975f5c5SAndroid Build Coastguard Worker QueryGL::QueryGL(gl::QueryType type) : QueryImpl(type) {}
56*8975f5c5SAndroid Build Coastguard Worker 
~QueryGL()57*8975f5c5SAndroid Build Coastguard Worker QueryGL::~QueryGL() {}
58*8975f5c5SAndroid Build Coastguard Worker 
StandardQueryGL(gl::QueryType type,const FunctionsGL * functions,StateManagerGL * stateManager)59*8975f5c5SAndroid Build Coastguard Worker StandardQueryGL::StandardQueryGL(gl::QueryType type,
60*8975f5c5SAndroid Build Coastguard Worker                                  const FunctionsGL *functions,
61*8975f5c5SAndroid Build Coastguard Worker                                  StateManagerGL *stateManager)
62*8975f5c5SAndroid Build Coastguard Worker     : QueryGL(type),
63*8975f5c5SAndroid Build Coastguard Worker       mFunctions(functions),
64*8975f5c5SAndroid Build Coastguard Worker       mStateManager(stateManager),
65*8975f5c5SAndroid Build Coastguard Worker       mActiveQuery(0),
66*8975f5c5SAndroid Build Coastguard Worker       mPendingQueries(),
67*8975f5c5SAndroid Build Coastguard Worker       mResultSum(0)
68*8975f5c5SAndroid Build Coastguard Worker {}
69*8975f5c5SAndroid Build Coastguard Worker 
~StandardQueryGL()70*8975f5c5SAndroid Build Coastguard Worker StandardQueryGL::~StandardQueryGL()
71*8975f5c5SAndroid Build Coastguard Worker {
72*8975f5c5SAndroid Build Coastguard Worker     clearInternalQueries();
73*8975f5c5SAndroid Build Coastguard Worker }
74*8975f5c5SAndroid Build Coastguard Worker 
clearInternalQueries()75*8975f5c5SAndroid Build Coastguard Worker void StandardQueryGL::clearInternalQueries()
76*8975f5c5SAndroid Build Coastguard Worker {
77*8975f5c5SAndroid Build Coastguard Worker     if (mActiveQuery != 0)
78*8975f5c5SAndroid Build Coastguard Worker     {
79*8975f5c5SAndroid Build Coastguard Worker         mStateManager->endQuery(mType, this, mActiveQuery);
80*8975f5c5SAndroid Build Coastguard Worker         mFunctions->deleteQueries(1, &mActiveQuery);
81*8975f5c5SAndroid Build Coastguard Worker         mActiveQuery = 0;
82*8975f5c5SAndroid Build Coastguard Worker     }
83*8975f5c5SAndroid Build Coastguard Worker 
84*8975f5c5SAndroid Build Coastguard Worker     while (!mPendingQueries.empty())
85*8975f5c5SAndroid Build Coastguard Worker     {
86*8975f5c5SAndroid Build Coastguard Worker         GLuint id = mPendingQueries.front();
87*8975f5c5SAndroid Build Coastguard Worker         mFunctions->deleteQueries(1, &id);
88*8975f5c5SAndroid Build Coastguard Worker         mPendingQueries.pop_front();
89*8975f5c5SAndroid Build Coastguard Worker     }
90*8975f5c5SAndroid Build Coastguard Worker }
91*8975f5c5SAndroid Build Coastguard Worker 
begin(const gl::Context * context)92*8975f5c5SAndroid Build Coastguard Worker angle::Result StandardQueryGL::begin(const gl::Context *context)
93*8975f5c5SAndroid Build Coastguard Worker {
94*8975f5c5SAndroid Build Coastguard Worker     clearInternalQueries();
95*8975f5c5SAndroid Build Coastguard Worker     mResultSum = 0;
96*8975f5c5SAndroid Build Coastguard Worker     return resume(context);
97*8975f5c5SAndroid Build Coastguard Worker }
98*8975f5c5SAndroid Build Coastguard Worker 
end(const gl::Context * context)99*8975f5c5SAndroid Build Coastguard Worker angle::Result StandardQueryGL::end(const gl::Context *context)
100*8975f5c5SAndroid Build Coastguard Worker {
101*8975f5c5SAndroid Build Coastguard Worker     return pause(context);
102*8975f5c5SAndroid Build Coastguard Worker }
103*8975f5c5SAndroid Build Coastguard Worker 
queryCounter(const gl::Context * context)104*8975f5c5SAndroid Build Coastguard Worker angle::Result StandardQueryGL::queryCounter(const gl::Context *context)
105*8975f5c5SAndroid Build Coastguard Worker {
106*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mType == gl::QueryType::Timestamp);
107*8975f5c5SAndroid Build Coastguard Worker 
108*8975f5c5SAndroid Build Coastguard Worker     // Directly create a query for the timestamp and add it to the pending query queue, as timestamp
109*8975f5c5SAndroid Build Coastguard Worker     // queries do not have the traditional begin/end block and never need to be paused/resumed
110*8975f5c5SAndroid Build Coastguard Worker     GLuint query;
111*8975f5c5SAndroid Build Coastguard Worker     mFunctions->genQueries(1, &query);
112*8975f5c5SAndroid Build Coastguard Worker     mFunctions->queryCounter(query, GL_TIMESTAMP);
113*8975f5c5SAndroid Build Coastguard Worker     mPendingQueries.push_back(query);
114*8975f5c5SAndroid Build Coastguard Worker 
115*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
116*8975f5c5SAndroid Build Coastguard Worker }
117*8975f5c5SAndroid Build Coastguard Worker 
118*8975f5c5SAndroid Build Coastguard Worker template <typename T>
getResultBase(const gl::Context * context,T * params)119*8975f5c5SAndroid Build Coastguard Worker angle::Result StandardQueryGL::getResultBase(const gl::Context *context, T *params)
120*8975f5c5SAndroid Build Coastguard Worker {
121*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mActiveQuery == 0);
122*8975f5c5SAndroid Build Coastguard Worker 
123*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(flush(context, true));
124*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mPendingQueries.empty());
125*8975f5c5SAndroid Build Coastguard Worker     *params = static_cast<T>(mResultSum);
126*8975f5c5SAndroid Build Coastguard Worker 
127*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
128*8975f5c5SAndroid Build Coastguard Worker }
129*8975f5c5SAndroid Build Coastguard Worker 
getResult(const gl::Context * context,GLint * params)130*8975f5c5SAndroid Build Coastguard Worker angle::Result StandardQueryGL::getResult(const gl::Context *context, GLint *params)
131*8975f5c5SAndroid Build Coastguard Worker {
132*8975f5c5SAndroid Build Coastguard Worker     return getResultBase(context, params);
133*8975f5c5SAndroid Build Coastguard Worker }
134*8975f5c5SAndroid Build Coastguard Worker 
getResult(const gl::Context * context,GLuint * params)135*8975f5c5SAndroid Build Coastguard Worker angle::Result StandardQueryGL::getResult(const gl::Context *context, GLuint *params)
136*8975f5c5SAndroid Build Coastguard Worker {
137*8975f5c5SAndroid Build Coastguard Worker     return getResultBase(context, params);
138*8975f5c5SAndroid Build Coastguard Worker }
139*8975f5c5SAndroid Build Coastguard Worker 
getResult(const gl::Context * context,GLint64 * params)140*8975f5c5SAndroid Build Coastguard Worker angle::Result StandardQueryGL::getResult(const gl::Context *context, GLint64 *params)
141*8975f5c5SAndroid Build Coastguard Worker {
142*8975f5c5SAndroid Build Coastguard Worker     return getResultBase(context, params);
143*8975f5c5SAndroid Build Coastguard Worker }
144*8975f5c5SAndroid Build Coastguard Worker 
getResult(const gl::Context * context,GLuint64 * params)145*8975f5c5SAndroid Build Coastguard Worker angle::Result StandardQueryGL::getResult(const gl::Context *context, GLuint64 *params)
146*8975f5c5SAndroid Build Coastguard Worker {
147*8975f5c5SAndroid Build Coastguard Worker     return getResultBase(context, params);
148*8975f5c5SAndroid Build Coastguard Worker }
149*8975f5c5SAndroid Build Coastguard Worker 
isResultAvailable(const gl::Context * context,bool * available)150*8975f5c5SAndroid Build Coastguard Worker angle::Result StandardQueryGL::isResultAvailable(const gl::Context *context, bool *available)
151*8975f5c5SAndroid Build Coastguard Worker {
152*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mActiveQuery == 0);
153*8975f5c5SAndroid Build Coastguard Worker 
154*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(flush(context, false));
155*8975f5c5SAndroid Build Coastguard Worker     *available = mPendingQueries.empty();
156*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
157*8975f5c5SAndroid Build Coastguard Worker }
158*8975f5c5SAndroid Build Coastguard Worker 
pause(const gl::Context * context)159*8975f5c5SAndroid Build Coastguard Worker angle::Result StandardQueryGL::pause(const gl::Context *context)
160*8975f5c5SAndroid Build Coastguard Worker {
161*8975f5c5SAndroid Build Coastguard Worker     if (mActiveQuery != 0)
162*8975f5c5SAndroid Build Coastguard Worker     {
163*8975f5c5SAndroid Build Coastguard Worker         mStateManager->endQuery(mType, this, mActiveQuery);
164*8975f5c5SAndroid Build Coastguard Worker 
165*8975f5c5SAndroid Build Coastguard Worker         mPendingQueries.push_back(mActiveQuery);
166*8975f5c5SAndroid Build Coastguard Worker         mActiveQuery = 0;
167*8975f5c5SAndroid Build Coastguard Worker     }
168*8975f5c5SAndroid Build Coastguard Worker 
169*8975f5c5SAndroid Build Coastguard Worker     // Flush to make sure the pending queries don't add up too much.
170*8975f5c5SAndroid Build Coastguard Worker     if (mPendingQueries.size() >= kPauseResumeFlushThreshold)
171*8975f5c5SAndroid Build Coastguard Worker     {
172*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(flush(context, false));
173*8975f5c5SAndroid Build Coastguard Worker     }
174*8975f5c5SAndroid Build Coastguard Worker 
175*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
176*8975f5c5SAndroid Build Coastguard Worker }
177*8975f5c5SAndroid Build Coastguard Worker 
resume(const gl::Context * context)178*8975f5c5SAndroid Build Coastguard Worker angle::Result StandardQueryGL::resume(const gl::Context *context)
179*8975f5c5SAndroid Build Coastguard Worker {
180*8975f5c5SAndroid Build Coastguard Worker     if (mActiveQuery == 0)
181*8975f5c5SAndroid Build Coastguard Worker     {
182*8975f5c5SAndroid Build Coastguard Worker         // Flush to make sure the pending queries don't add up too much.
183*8975f5c5SAndroid Build Coastguard Worker         if (mPendingQueries.size() >= kPauseResumeFlushThreshold)
184*8975f5c5SAndroid Build Coastguard Worker         {
185*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(flush(context, false));
186*8975f5c5SAndroid Build Coastguard Worker         }
187*8975f5c5SAndroid Build Coastguard Worker 
188*8975f5c5SAndroid Build Coastguard Worker         mFunctions->genQueries(1, &mActiveQuery);
189*8975f5c5SAndroid Build Coastguard Worker         mStateManager->beginQuery(mType, this, mActiveQuery);
190*8975f5c5SAndroid Build Coastguard Worker 
191*8975f5c5SAndroid Build Coastguard Worker         ContextGL *contextGL = GetImplAs<ContextGL>(context);
192*8975f5c5SAndroid Build Coastguard Worker         contextGL->markWorkSubmitted();
193*8975f5c5SAndroid Build Coastguard Worker     }
194*8975f5c5SAndroid Build Coastguard Worker 
195*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
196*8975f5c5SAndroid Build Coastguard Worker }
197*8975f5c5SAndroid Build Coastguard Worker 
flush(const gl::Context * context,bool force)198*8975f5c5SAndroid Build Coastguard Worker angle::Result StandardQueryGL::flush(const gl::Context *context, bool force)
199*8975f5c5SAndroid Build Coastguard Worker {
200*8975f5c5SAndroid Build Coastguard Worker     while (!mPendingQueries.empty())
201*8975f5c5SAndroid Build Coastguard Worker     {
202*8975f5c5SAndroid Build Coastguard Worker         GLuint id = mPendingQueries.front();
203*8975f5c5SAndroid Build Coastguard Worker         if (!force)
204*8975f5c5SAndroid Build Coastguard Worker         {
205*8975f5c5SAndroid Build Coastguard Worker             GLuint resultAvailable = 0;
206*8975f5c5SAndroid Build Coastguard Worker             mFunctions->getQueryObjectuiv(id, GL_QUERY_RESULT_AVAILABLE, &resultAvailable);
207*8975f5c5SAndroid Build Coastguard Worker             if (resultAvailable == GL_FALSE)
208*8975f5c5SAndroid Build Coastguard Worker             {
209*8975f5c5SAndroid Build Coastguard Worker                 return angle::Result::Continue;
210*8975f5c5SAndroid Build Coastguard Worker             }
211*8975f5c5SAndroid Build Coastguard Worker         }
212*8975f5c5SAndroid Build Coastguard Worker 
213*8975f5c5SAndroid Build Coastguard Worker         // Even though getQueryObjectui64v was introduced for timer queries, there is nothing in the
214*8975f5c5SAndroid Build Coastguard Worker         // standard that says that it doesn't work for any other queries. It also passes on all the
215*8975f5c5SAndroid Build Coastguard Worker         // trybots, so we use it if it is available
216*8975f5c5SAndroid Build Coastguard Worker         if (mFunctions->getQueryObjectui64v != nullptr)
217*8975f5c5SAndroid Build Coastguard Worker         {
218*8975f5c5SAndroid Build Coastguard Worker             GLuint64 result = 0;
219*8975f5c5SAndroid Build Coastguard Worker             mFunctions->getQueryObjectui64v(id, GL_QUERY_RESULT, &result);
220*8975f5c5SAndroid Build Coastguard Worker             mResultSum = MergeQueryResults(mType, mResultSum, result);
221*8975f5c5SAndroid Build Coastguard Worker         }
222*8975f5c5SAndroid Build Coastguard Worker         else
223*8975f5c5SAndroid Build Coastguard Worker         {
224*8975f5c5SAndroid Build Coastguard Worker             GLuint result = 0;
225*8975f5c5SAndroid Build Coastguard Worker             mFunctions->getQueryObjectuiv(id, GL_QUERY_RESULT, &result);
226*8975f5c5SAndroid Build Coastguard Worker             mResultSum = MergeQueryResults(mType, mResultSum, static_cast<GLuint64>(result));
227*8975f5c5SAndroid Build Coastguard Worker         }
228*8975f5c5SAndroid Build Coastguard Worker 
229*8975f5c5SAndroid Build Coastguard Worker         mFunctions->deleteQueries(1, &id);
230*8975f5c5SAndroid Build Coastguard Worker 
231*8975f5c5SAndroid Build Coastguard Worker         mPendingQueries.pop_front();
232*8975f5c5SAndroid Build Coastguard Worker     }
233*8975f5c5SAndroid Build Coastguard Worker 
234*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
235*8975f5c5SAndroid Build Coastguard Worker }
236*8975f5c5SAndroid Build Coastguard Worker 
237*8975f5c5SAndroid Build Coastguard Worker class SyncProviderGL
238*8975f5c5SAndroid Build Coastguard Worker {
239*8975f5c5SAndroid Build Coastguard Worker   public:
~SyncProviderGL()240*8975f5c5SAndroid Build Coastguard Worker     virtual ~SyncProviderGL() {}
init(const gl::Context * context,gl::QueryType queryType)241*8975f5c5SAndroid Build Coastguard Worker     virtual angle::Result init(const gl::Context *context, gl::QueryType queryType)
242*8975f5c5SAndroid Build Coastguard Worker     {
243*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
244*8975f5c5SAndroid Build Coastguard Worker     }
245*8975f5c5SAndroid Build Coastguard Worker     virtual angle::Result flush(const gl::Context *context, bool force, bool *finished) = 0;
246*8975f5c5SAndroid Build Coastguard Worker };
247*8975f5c5SAndroid Build Coastguard Worker 
248*8975f5c5SAndroid Build Coastguard Worker class SyncProviderGLSync : public SyncProviderGL
249*8975f5c5SAndroid Build Coastguard Worker {
250*8975f5c5SAndroid Build Coastguard Worker   public:
SyncProviderGLSync(const FunctionsGL * functions)251*8975f5c5SAndroid Build Coastguard Worker     SyncProviderGLSync(const FunctionsGL *functions) : mFunctions(functions), mSync(nullptr) {}
252*8975f5c5SAndroid Build Coastguard Worker 
~SyncProviderGLSync()253*8975f5c5SAndroid Build Coastguard Worker     ~SyncProviderGLSync() override { mFunctions->deleteSync(mSync); }
254*8975f5c5SAndroid Build Coastguard Worker 
init(const gl::Context * context,gl::QueryType type)255*8975f5c5SAndroid Build Coastguard Worker     angle::Result init(const gl::Context *context, gl::QueryType type) override
256*8975f5c5SAndroid Build Coastguard Worker     {
257*8975f5c5SAndroid Build Coastguard Worker         ContextGL *contextGL = GetImplAs<ContextGL>(context);
258*8975f5c5SAndroid Build Coastguard Worker         mSync                = mFunctions->fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
259*8975f5c5SAndroid Build Coastguard Worker         ANGLE_CHECK(contextGL, mSync != 0, "glFenceSync failed to create a GLsync object.",
260*8975f5c5SAndroid Build Coastguard Worker                     GL_OUT_OF_MEMORY);
261*8975f5c5SAndroid Build Coastguard Worker         contextGL->markWorkSubmitted();
262*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
263*8975f5c5SAndroid Build Coastguard Worker     }
264*8975f5c5SAndroid Build Coastguard Worker 
flush(const gl::Context * context,bool force,bool * finished)265*8975f5c5SAndroid Build Coastguard Worker     angle::Result flush(const gl::Context *context, bool force, bool *finished) override
266*8975f5c5SAndroid Build Coastguard Worker     {
267*8975f5c5SAndroid Build Coastguard Worker         if (force)
268*8975f5c5SAndroid Build Coastguard Worker         {
269*8975f5c5SAndroid Build Coastguard Worker             mFunctions->clientWaitSync(mSync, 0, 0);
270*8975f5c5SAndroid Build Coastguard Worker             *finished = true;
271*8975f5c5SAndroid Build Coastguard Worker         }
272*8975f5c5SAndroid Build Coastguard Worker         else
273*8975f5c5SAndroid Build Coastguard Worker         {
274*8975f5c5SAndroid Build Coastguard Worker             GLint value = 0;
275*8975f5c5SAndroid Build Coastguard Worker             mFunctions->getSynciv(mSync, GL_SYNC_STATUS, 1, nullptr, &value);
276*8975f5c5SAndroid Build Coastguard Worker             *finished = (value == GL_SIGNALED);
277*8975f5c5SAndroid Build Coastguard Worker         }
278*8975f5c5SAndroid Build Coastguard Worker 
279*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
280*8975f5c5SAndroid Build Coastguard Worker     }
281*8975f5c5SAndroid Build Coastguard Worker 
282*8975f5c5SAndroid Build Coastguard Worker   private:
283*8975f5c5SAndroid Build Coastguard Worker     const FunctionsGL *mFunctions;
284*8975f5c5SAndroid Build Coastguard Worker     GLsync mSync;
285*8975f5c5SAndroid Build Coastguard Worker };
286*8975f5c5SAndroid Build Coastguard Worker 
287*8975f5c5SAndroid Build Coastguard Worker class SyncProviderGLQuery : public SyncProviderGL
288*8975f5c5SAndroid Build Coastguard Worker {
289*8975f5c5SAndroid Build Coastguard Worker   public:
SyncProviderGLQuery(const FunctionsGL * functions)290*8975f5c5SAndroid Build Coastguard Worker     SyncProviderGLQuery(const FunctionsGL *functions) : mFunctions(functions), mQuery(0) {}
291*8975f5c5SAndroid Build Coastguard Worker 
init(const gl::Context * context,gl::QueryType type)292*8975f5c5SAndroid Build Coastguard Worker     angle::Result init(const gl::Context *context, gl::QueryType type) override
293*8975f5c5SAndroid Build Coastguard Worker     {
294*8975f5c5SAndroid Build Coastguard Worker         StateManagerGL *stateManager = GetStateManagerGL(context);
295*8975f5c5SAndroid Build Coastguard Worker 
296*8975f5c5SAndroid Build Coastguard Worker         mFunctions->genQueries(1, &mQuery);
297*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(stateManager->pauseQuery(context, type));
298*8975f5c5SAndroid Build Coastguard Worker         mFunctions->beginQuery(ToGLenum(type), mQuery);
299*8975f5c5SAndroid Build Coastguard Worker         mFunctions->endQuery(ToGLenum(type));
300*8975f5c5SAndroid Build Coastguard Worker         return stateManager->resumeQuery(context, type);
301*8975f5c5SAndroid Build Coastguard Worker     }
302*8975f5c5SAndroid Build Coastguard Worker 
~SyncProviderGLQuery()303*8975f5c5SAndroid Build Coastguard Worker     ~SyncProviderGLQuery() override { mFunctions->deleteQueries(1, &mQuery); }
304*8975f5c5SAndroid Build Coastguard Worker 
flush(const gl::Context * context,bool force,bool * finished)305*8975f5c5SAndroid Build Coastguard Worker     angle::Result flush(const gl::Context *context, bool force, bool *finished) override
306*8975f5c5SAndroid Build Coastguard Worker     {
307*8975f5c5SAndroid Build Coastguard Worker         if (force)
308*8975f5c5SAndroid Build Coastguard Worker         {
309*8975f5c5SAndroid Build Coastguard Worker             GLint result = 0;
310*8975f5c5SAndroid Build Coastguard Worker             mFunctions->getQueryObjectiv(mQuery, GL_QUERY_RESULT, &result);
311*8975f5c5SAndroid Build Coastguard Worker             *finished = true;
312*8975f5c5SAndroid Build Coastguard Worker         }
313*8975f5c5SAndroid Build Coastguard Worker         else
314*8975f5c5SAndroid Build Coastguard Worker         {
315*8975f5c5SAndroid Build Coastguard Worker             GLint available = 0;
316*8975f5c5SAndroid Build Coastguard Worker             mFunctions->getQueryObjectiv(mQuery, GL_QUERY_RESULT_AVAILABLE, &available);
317*8975f5c5SAndroid Build Coastguard Worker             *finished = (available == GL_TRUE);
318*8975f5c5SAndroid Build Coastguard Worker         }
319*8975f5c5SAndroid Build Coastguard Worker 
320*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
321*8975f5c5SAndroid Build Coastguard Worker     }
322*8975f5c5SAndroid Build Coastguard Worker 
323*8975f5c5SAndroid Build Coastguard Worker   private:
324*8975f5c5SAndroid Build Coastguard Worker     const FunctionsGL *mFunctions;
325*8975f5c5SAndroid Build Coastguard Worker     GLuint mQuery;
326*8975f5c5SAndroid Build Coastguard Worker };
327*8975f5c5SAndroid Build Coastguard Worker 
SyncQueryGL(gl::QueryType type,const FunctionsGL * functions)328*8975f5c5SAndroid Build Coastguard Worker SyncQueryGL::SyncQueryGL(gl::QueryType type, const FunctionsGL *functions)
329*8975f5c5SAndroid Build Coastguard Worker     : QueryGL(type), mFunctions(functions), mSyncProvider(nullptr), mFinished(false)
330*8975f5c5SAndroid Build Coastguard Worker {
331*8975f5c5SAndroid Build Coastguard Worker     ASSERT(IsSupported(mFunctions));
332*8975f5c5SAndroid Build Coastguard Worker     ASSERT(type == gl::QueryType::CommandsCompleted);
333*8975f5c5SAndroid Build Coastguard Worker }
334*8975f5c5SAndroid Build Coastguard Worker 
~SyncQueryGL()335*8975f5c5SAndroid Build Coastguard Worker SyncQueryGL::~SyncQueryGL() {}
336*8975f5c5SAndroid Build Coastguard Worker 
IsSupported(const FunctionsGL * functions)337*8975f5c5SAndroid Build Coastguard Worker bool SyncQueryGL::IsSupported(const FunctionsGL *functions)
338*8975f5c5SAndroid Build Coastguard Worker {
339*8975f5c5SAndroid Build Coastguard Worker     return nativegl::SupportsFenceSync(functions) || nativegl::SupportsOcclusionQueries(functions);
340*8975f5c5SAndroid Build Coastguard Worker }
341*8975f5c5SAndroid Build Coastguard Worker 
begin(const gl::Context * context)342*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncQueryGL::begin(const gl::Context *context)
343*8975f5c5SAndroid Build Coastguard Worker {
344*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
345*8975f5c5SAndroid Build Coastguard Worker }
346*8975f5c5SAndroid Build Coastguard Worker 
end(const gl::Context * context)347*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncQueryGL::end(const gl::Context *context)
348*8975f5c5SAndroid Build Coastguard Worker {
349*8975f5c5SAndroid Build Coastguard Worker     if (nativegl::SupportsFenceSync(mFunctions))
350*8975f5c5SAndroid Build Coastguard Worker     {
351*8975f5c5SAndroid Build Coastguard Worker         mSyncProvider.reset(new SyncProviderGLSync(mFunctions));
352*8975f5c5SAndroid Build Coastguard Worker     }
353*8975f5c5SAndroid Build Coastguard Worker     else if (nativegl::SupportsOcclusionQueries(mFunctions))
354*8975f5c5SAndroid Build Coastguard Worker     {
355*8975f5c5SAndroid Build Coastguard Worker         mSyncProvider.reset(new SyncProviderGLQuery(mFunctions));
356*8975f5c5SAndroid Build Coastguard Worker     }
357*8975f5c5SAndroid Build Coastguard Worker     else
358*8975f5c5SAndroid Build Coastguard Worker     {
359*8975f5c5SAndroid Build Coastguard Worker         ANGLE_GL_UNREACHABLE(GetImplAs<ContextGL>(context));
360*8975f5c5SAndroid Build Coastguard Worker     }
361*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mSyncProvider->init(context, gl::QueryType::AnySamples));
362*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
363*8975f5c5SAndroid Build Coastguard Worker }
364*8975f5c5SAndroid Build Coastguard Worker 
queryCounter(const gl::Context * context)365*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncQueryGL::queryCounter(const gl::Context *context)
366*8975f5c5SAndroid Build Coastguard Worker {
367*8975f5c5SAndroid Build Coastguard Worker     UNREACHABLE();
368*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
369*8975f5c5SAndroid Build Coastguard Worker }
370*8975f5c5SAndroid Build Coastguard Worker 
getResult(const gl::Context * context,GLint * params)371*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncQueryGL::getResult(const gl::Context *context, GLint *params)
372*8975f5c5SAndroid Build Coastguard Worker {
373*8975f5c5SAndroid Build Coastguard Worker     return getResultBase(context, params);
374*8975f5c5SAndroid Build Coastguard Worker }
375*8975f5c5SAndroid Build Coastguard Worker 
getResult(const gl::Context * context,GLuint * params)376*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncQueryGL::getResult(const gl::Context *context, GLuint *params)
377*8975f5c5SAndroid Build Coastguard Worker {
378*8975f5c5SAndroid Build Coastguard Worker     return getResultBase(context, params);
379*8975f5c5SAndroid Build Coastguard Worker }
380*8975f5c5SAndroid Build Coastguard Worker 
getResult(const gl::Context * context,GLint64 * params)381*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncQueryGL::getResult(const gl::Context *context, GLint64 *params)
382*8975f5c5SAndroid Build Coastguard Worker {
383*8975f5c5SAndroid Build Coastguard Worker     return getResultBase(context, params);
384*8975f5c5SAndroid Build Coastguard Worker }
385*8975f5c5SAndroid Build Coastguard Worker 
getResult(const gl::Context * context,GLuint64 * params)386*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncQueryGL::getResult(const gl::Context *context, GLuint64 *params)
387*8975f5c5SAndroid Build Coastguard Worker {
388*8975f5c5SAndroid Build Coastguard Worker     return getResultBase(context, params);
389*8975f5c5SAndroid Build Coastguard Worker }
390*8975f5c5SAndroid Build Coastguard Worker 
isResultAvailable(const gl::Context * context,bool * available)391*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncQueryGL::isResultAvailable(const gl::Context *context, bool *available)
392*8975f5c5SAndroid Build Coastguard Worker {
393*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(flush(context, false));
394*8975f5c5SAndroid Build Coastguard Worker     *available = mFinished;
395*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
396*8975f5c5SAndroid Build Coastguard Worker }
397*8975f5c5SAndroid Build Coastguard Worker 
pause(const gl::Context * context)398*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncQueryGL::pause(const gl::Context *context)
399*8975f5c5SAndroid Build Coastguard Worker {
400*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
401*8975f5c5SAndroid Build Coastguard Worker }
402*8975f5c5SAndroid Build Coastguard Worker 
resume(const gl::Context * context)403*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncQueryGL::resume(const gl::Context *context)
404*8975f5c5SAndroid Build Coastguard Worker {
405*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
406*8975f5c5SAndroid Build Coastguard Worker }
407*8975f5c5SAndroid Build Coastguard Worker 
flush(const gl::Context * context,bool force)408*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncQueryGL::flush(const gl::Context *context, bool force)
409*8975f5c5SAndroid Build Coastguard Worker {
410*8975f5c5SAndroid Build Coastguard Worker     if (mSyncProvider == nullptr)
411*8975f5c5SAndroid Build Coastguard Worker     {
412*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mFinished);
413*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
414*8975f5c5SAndroid Build Coastguard Worker     }
415*8975f5c5SAndroid Build Coastguard Worker 
416*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mSyncProvider->flush(context, force, &mFinished));
417*8975f5c5SAndroid Build Coastguard Worker     if (mFinished)
418*8975f5c5SAndroid Build Coastguard Worker     {
419*8975f5c5SAndroid Build Coastguard Worker         mSyncProvider.reset();
420*8975f5c5SAndroid Build Coastguard Worker     }
421*8975f5c5SAndroid Build Coastguard Worker 
422*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
423*8975f5c5SAndroid Build Coastguard Worker }
424*8975f5c5SAndroid Build Coastguard Worker 
425*8975f5c5SAndroid Build Coastguard Worker template <typename T>
getResultBase(const gl::Context * context,T * params)426*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncQueryGL::getResultBase(const gl::Context *context, T *params)
427*8975f5c5SAndroid Build Coastguard Worker {
428*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(flush(context, true));
429*8975f5c5SAndroid Build Coastguard Worker     *params = static_cast<T>(mFinished ? GL_TRUE : GL_FALSE);
430*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
431*8975f5c5SAndroid Build Coastguard Worker }
432*8975f5c5SAndroid Build Coastguard Worker }  // namespace rx
433