xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/vulkan/QueryVk.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2016 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 // QueryVk.cpp:
7*8975f5c5SAndroid Build Coastguard Worker //    Implements the class methods for QueryVk.
8*8975f5c5SAndroid Build Coastguard Worker //
9*8975f5c5SAndroid Build Coastguard Worker 
10*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/QueryVk.h"
11*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
12*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/TransformFeedback.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/ContextVk.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/TransformFeedbackVk.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/vk_renderer.h"
16*8975f5c5SAndroid Build Coastguard Worker 
17*8975f5c5SAndroid Build Coastguard Worker #include "common/debug.h"
18*8975f5c5SAndroid Build Coastguard Worker 
19*8975f5c5SAndroid Build Coastguard Worker namespace rx
20*8975f5c5SAndroid Build Coastguard Worker {
21*8975f5c5SAndroid Build Coastguard Worker 
22*8975f5c5SAndroid Build Coastguard Worker namespace
23*8975f5c5SAndroid Build Coastguard Worker {
24*8975f5c5SAndroid Build Coastguard Worker struct QueryReleaseHelper
25*8975f5c5SAndroid Build Coastguard Worker {
operator ()rx::__anon14d9df8f0111::QueryReleaseHelper26*8975f5c5SAndroid Build Coastguard Worker     void operator()(vk::QueryHelper &&query) { queryPool->freeQuery(contextVk, &query); }
27*8975f5c5SAndroid Build Coastguard Worker 
28*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk;
29*8975f5c5SAndroid Build Coastguard Worker     vk::DynamicQueryPool *queryPool;
30*8975f5c5SAndroid Build Coastguard Worker };
31*8975f5c5SAndroid Build Coastguard Worker 
IsRenderPassQuery(ContextVk * contextVk,gl::QueryType type)32*8975f5c5SAndroid Build Coastguard Worker bool IsRenderPassQuery(ContextVk *contextVk, gl::QueryType type)
33*8975f5c5SAndroid Build Coastguard Worker {
34*8975f5c5SAndroid Build Coastguard Worker     switch (type)
35*8975f5c5SAndroid Build Coastguard Worker     {
36*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::AnySamples:
37*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::AnySamplesConservative:
38*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::PrimitivesGenerated:
39*8975f5c5SAndroid Build Coastguard Worker             return true;
40*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::TransformFeedbackPrimitivesWritten:
41*8975f5c5SAndroid Build Coastguard Worker             return contextVk->getFeatures().supportsTransformFeedbackExtension.enabled;
42*8975f5c5SAndroid Build Coastguard Worker         default:
43*8975f5c5SAndroid Build Coastguard Worker             return false;
44*8975f5c5SAndroid Build Coastguard Worker     }
45*8975f5c5SAndroid Build Coastguard Worker }
46*8975f5c5SAndroid Build Coastguard Worker 
IsEmulatedTransformFeedbackQuery(ContextVk * contextVk,gl::QueryType type)47*8975f5c5SAndroid Build Coastguard Worker bool IsEmulatedTransformFeedbackQuery(ContextVk *contextVk, gl::QueryType type)
48*8975f5c5SAndroid Build Coastguard Worker {
49*8975f5c5SAndroid Build Coastguard Worker     return type == gl::QueryType::TransformFeedbackPrimitivesWritten &&
50*8975f5c5SAndroid Build Coastguard Worker            contextVk->getFeatures().emulateTransformFeedback.enabled;
51*8975f5c5SAndroid Build Coastguard Worker }
52*8975f5c5SAndroid Build Coastguard Worker 
IsPrimitivesGeneratedQueryShared(ContextVk * contextVk)53*8975f5c5SAndroid Build Coastguard Worker bool IsPrimitivesGeneratedQueryShared(ContextVk *contextVk)
54*8975f5c5SAndroid Build Coastguard Worker {
55*8975f5c5SAndroid Build Coastguard Worker     return !contextVk->getFeatures().supportsPrimitivesGeneratedQuery.enabled &&
56*8975f5c5SAndroid Build Coastguard Worker            !contextVk->getFeatures().supportsPipelineStatisticsQuery.enabled;
57*8975f5c5SAndroid Build Coastguard Worker }
58*8975f5c5SAndroid Build Coastguard Worker 
GetShareQuery(ContextVk * contextVk,gl::QueryType type)59*8975f5c5SAndroid Build Coastguard Worker QueryVk *GetShareQuery(ContextVk *contextVk, gl::QueryType type)
60*8975f5c5SAndroid Build Coastguard Worker {
61*8975f5c5SAndroid Build Coastguard Worker     QueryVk *shareQuery = nullptr;
62*8975f5c5SAndroid Build Coastguard Worker 
63*8975f5c5SAndroid Build Coastguard Worker     // If the primitives generated query has its own dedicated Vulkan query, there's no sharing.
64*8975f5c5SAndroid Build Coastguard Worker     if (!IsPrimitivesGeneratedQueryShared(contextVk))
65*8975f5c5SAndroid Build Coastguard Worker     {
66*8975f5c5SAndroid Build Coastguard Worker         return nullptr;
67*8975f5c5SAndroid Build Coastguard Worker     }
68*8975f5c5SAndroid Build Coastguard Worker 
69*8975f5c5SAndroid Build Coastguard Worker     switch (type)
70*8975f5c5SAndroid Build Coastguard Worker     {
71*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::PrimitivesGenerated:
72*8975f5c5SAndroid Build Coastguard Worker             shareQuery = contextVk->getActiveRenderPassQuery(
73*8975f5c5SAndroid Build Coastguard Worker                 gl::QueryType::TransformFeedbackPrimitivesWritten);
74*8975f5c5SAndroid Build Coastguard Worker             break;
75*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::TransformFeedbackPrimitivesWritten:
76*8975f5c5SAndroid Build Coastguard Worker             shareQuery = contextVk->getActiveRenderPassQuery(gl::QueryType::PrimitivesGenerated);
77*8975f5c5SAndroid Build Coastguard Worker             break;
78*8975f5c5SAndroid Build Coastguard Worker         default:
79*8975f5c5SAndroid Build Coastguard Worker             break;
80*8975f5c5SAndroid Build Coastguard Worker     }
81*8975f5c5SAndroid Build Coastguard Worker 
82*8975f5c5SAndroid Build Coastguard Worker     return shareQuery;
83*8975f5c5SAndroid Build Coastguard Worker }
84*8975f5c5SAndroid Build Coastguard Worker 
85*8975f5c5SAndroid Build Coastguard Worker // When a render pass starts/ends, onRenderPassStart/End  is called for all active queries.  For
86*8975f5c5SAndroid Build Coastguard Worker // shared queries, the one that is called first would actually manage the query helper begin/end and
87*8975f5c5SAndroid Build Coastguard Worker // allocation, and the one that follows would share it.  PrimitivesGenerated and
88*8975f5c5SAndroid Build Coastguard Worker // TransformFeedbackPrimitivesWritten share queries, and the former is processed first.
GetOnRenderPassStartEndShareQuery(ContextVk * contextVk,gl::QueryType type)89*8975f5c5SAndroid Build Coastguard Worker QueryVk *GetOnRenderPassStartEndShareQuery(ContextVk *contextVk, gl::QueryType type)
90*8975f5c5SAndroid Build Coastguard Worker {
91*8975f5c5SAndroid Build Coastguard Worker     static_assert(
92*8975f5c5SAndroid Build Coastguard Worker         gl::QueryType::PrimitivesGenerated < gl::QueryType::TransformFeedbackPrimitivesWritten,
93*8975f5c5SAndroid Build Coastguard Worker         "incorrect assumption about the order in which queries are started in a render pass");
94*8975f5c5SAndroid Build Coastguard Worker 
95*8975f5c5SAndroid Build Coastguard Worker     if (type != gl::QueryType::TransformFeedbackPrimitivesWritten ||
96*8975f5c5SAndroid Build Coastguard Worker         !IsPrimitivesGeneratedQueryShared(contextVk))
97*8975f5c5SAndroid Build Coastguard Worker     {
98*8975f5c5SAndroid Build Coastguard Worker         return nullptr;
99*8975f5c5SAndroid Build Coastguard Worker     }
100*8975f5c5SAndroid Build Coastguard Worker 
101*8975f5c5SAndroid Build Coastguard Worker     // For TransformFeedbackPrimitivesWritten, return the already-processed PrimitivesGenerated
102*8975f5c5SAndroid Build Coastguard Worker     // share query.
103*8975f5c5SAndroid Build Coastguard Worker     return contextVk->getActiveRenderPassQuery(gl::QueryType::PrimitivesGenerated);
104*8975f5c5SAndroid Build Coastguard Worker }
105*8975f5c5SAndroid Build Coastguard Worker }  // anonymous namespace
106*8975f5c5SAndroid Build Coastguard Worker 
QueryVk(gl::QueryType type)107*8975f5c5SAndroid Build Coastguard Worker QueryVk::QueryVk(gl::QueryType type)
108*8975f5c5SAndroid Build Coastguard Worker     : QueryImpl(type),
109*8975f5c5SAndroid Build Coastguard Worker       mTransformFeedbackPrimitivesDrawn(0),
110*8975f5c5SAndroid Build Coastguard Worker       mCachedResult(0),
111*8975f5c5SAndroid Build Coastguard Worker       mCachedResultValid(false)
112*8975f5c5SAndroid Build Coastguard Worker {}
113*8975f5c5SAndroid Build Coastguard Worker 
114*8975f5c5SAndroid Build Coastguard Worker QueryVk::~QueryVk() = default;
115*8975f5c5SAndroid Build Coastguard Worker 
allocateQuery(ContextVk * contextVk)116*8975f5c5SAndroid Build Coastguard Worker angle::Result QueryVk::allocateQuery(ContextVk *contextVk)
117*8975f5c5SAndroid Build Coastguard Worker {
118*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mQueryHelper.isReferenced());
119*8975f5c5SAndroid Build Coastguard Worker     mQueryHelper.setUnreferenced(new vk::RefCounted<vk::QueryHelper>);
120*8975f5c5SAndroid Build Coastguard Worker 
121*8975f5c5SAndroid Build Coastguard Worker     // When used with multiview, render pass queries write as many queries as the number of views.
122*8975f5c5SAndroid Build Coastguard Worker     // Render pass queries are always allocated at the beginning of the render pass, so the number
123*8975f5c5SAndroid Build Coastguard Worker     // of views is known at this time.
124*8975f5c5SAndroid Build Coastguard Worker     uint32_t queryCount = 1;
125*8975f5c5SAndroid Build Coastguard Worker     if (IsRenderPassQuery(contextVk, mType))
126*8975f5c5SAndroid Build Coastguard Worker     {
127*8975f5c5SAndroid Build Coastguard Worker         ASSERT(contextVk->hasActiveRenderPass());
128*8975f5c5SAndroid Build Coastguard Worker         queryCount = std::max(contextVk->getCurrentViewCount(), 1u);
129*8975f5c5SAndroid Build Coastguard Worker     }
130*8975f5c5SAndroid Build Coastguard Worker 
131*8975f5c5SAndroid Build Coastguard Worker     return contextVk->getQueryPool(mType)->allocateQuery(contextVk, &mQueryHelper.get(),
132*8975f5c5SAndroid Build Coastguard Worker                                                          queryCount);
133*8975f5c5SAndroid Build Coastguard Worker }
134*8975f5c5SAndroid Build Coastguard Worker 
assignSharedQuery(QueryVk * shareQuery)135*8975f5c5SAndroid Build Coastguard Worker void QueryVk::assignSharedQuery(QueryVk *shareQuery)
136*8975f5c5SAndroid Build Coastguard Worker {
137*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mQueryHelper.isReferenced());
138*8975f5c5SAndroid Build Coastguard Worker     ASSERT(shareQuery->mQueryHelper.isReferenced());
139*8975f5c5SAndroid Build Coastguard Worker     mQueryHelper.copyUnreferenced(shareQuery->mQueryHelper);
140*8975f5c5SAndroid Build Coastguard Worker }
141*8975f5c5SAndroid Build Coastguard Worker 
releaseQueries(ContextVk * contextVk)142*8975f5c5SAndroid Build Coastguard Worker void QueryVk::releaseQueries(ContextVk *contextVk)
143*8975f5c5SAndroid Build Coastguard Worker {
144*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!IsEmulatedTransformFeedbackQuery(contextVk, mType));
145*8975f5c5SAndroid Build Coastguard Worker 
146*8975f5c5SAndroid Build Coastguard Worker     vk::DynamicQueryPool *queryPool = contextVk->getQueryPool(mType);
147*8975f5c5SAndroid Build Coastguard Worker 
148*8975f5c5SAndroid Build Coastguard Worker     // Free the main query
149*8975f5c5SAndroid Build Coastguard Worker     if (mQueryHelper.isReferenced())
150*8975f5c5SAndroid Build Coastguard Worker     {
151*8975f5c5SAndroid Build Coastguard Worker         QueryReleaseHelper releaseHelper = {contextVk, queryPool};
152*8975f5c5SAndroid Build Coastguard Worker         mQueryHelper.resetAndRelease(&releaseHelper);
153*8975f5c5SAndroid Build Coastguard Worker     }
154*8975f5c5SAndroid Build Coastguard Worker     // Free the secondary query used to emulate TimeElapsed
155*8975f5c5SAndroid Build Coastguard Worker     queryPool->freeQuery(contextVk, &mQueryHelperTimeElapsedBegin);
156*8975f5c5SAndroid Build Coastguard Worker 
157*8975f5c5SAndroid Build Coastguard Worker     // Free any stashed queries used to support queries that start and stop with the render pass.
158*8975f5c5SAndroid Build Coastguard Worker     releaseStashedQueries(contextVk);
159*8975f5c5SAndroid Build Coastguard Worker }
160*8975f5c5SAndroid Build Coastguard Worker 
releaseStashedQueries(ContextVk * contextVk)161*8975f5c5SAndroid Build Coastguard Worker void QueryVk::releaseStashedQueries(ContextVk *contextVk)
162*8975f5c5SAndroid Build Coastguard Worker {
163*8975f5c5SAndroid Build Coastguard Worker     vk::DynamicQueryPool *queryPool = contextVk->getQueryPool(mType);
164*8975f5c5SAndroid Build Coastguard Worker 
165*8975f5c5SAndroid Build Coastguard Worker     for (vk::Shared<vk::QueryHelper> &query : mStashedQueryHelpers)
166*8975f5c5SAndroid Build Coastguard Worker     {
167*8975f5c5SAndroid Build Coastguard Worker         ASSERT(query.isReferenced());
168*8975f5c5SAndroid Build Coastguard Worker 
169*8975f5c5SAndroid Build Coastguard Worker         QueryReleaseHelper releaseHelper = {contextVk, queryPool};
170*8975f5c5SAndroid Build Coastguard Worker         query.resetAndRelease(&releaseHelper);
171*8975f5c5SAndroid Build Coastguard Worker     }
172*8975f5c5SAndroid Build Coastguard Worker     mStashedQueryHelpers.clear();
173*8975f5c5SAndroid Build Coastguard Worker }
174*8975f5c5SAndroid Build Coastguard Worker 
onDestroy(const gl::Context * context)175*8975f5c5SAndroid Build Coastguard Worker void QueryVk::onDestroy(const gl::Context *context)
176*8975f5c5SAndroid Build Coastguard Worker {
177*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
178*8975f5c5SAndroid Build Coastguard Worker     if (!IsEmulatedTransformFeedbackQuery(contextVk, mType))
179*8975f5c5SAndroid Build Coastguard Worker     {
180*8975f5c5SAndroid Build Coastguard Worker         releaseQueries(contextVk);
181*8975f5c5SAndroid Build Coastguard Worker     }
182*8975f5c5SAndroid Build Coastguard Worker }
183*8975f5c5SAndroid Build Coastguard Worker 
stashQueryHelper()184*8975f5c5SAndroid Build Coastguard Worker void QueryVk::stashQueryHelper()
185*8975f5c5SAndroid Build Coastguard Worker {
186*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mQueryHelper.isReferenced());
187*8975f5c5SAndroid Build Coastguard Worker     mStashedQueryHelpers.push_back(std::move(mQueryHelper));
188*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mQueryHelper.isReferenced());
189*8975f5c5SAndroid Build Coastguard Worker }
190*8975f5c5SAndroid Build Coastguard Worker 
onRenderPassStart(ContextVk * contextVk)191*8975f5c5SAndroid Build Coastguard Worker angle::Result QueryVk::onRenderPassStart(ContextVk *contextVk)
192*8975f5c5SAndroid Build Coastguard Worker {
193*8975f5c5SAndroid Build Coastguard Worker     ASSERT(IsRenderPassQuery(contextVk, mType));
194*8975f5c5SAndroid Build Coastguard Worker 
195*8975f5c5SAndroid Build Coastguard Worker     // If there is a query helper already, stash it and allocate a new one for this render pass.
196*8975f5c5SAndroid Build Coastguard Worker     if (mQueryHelper.isReferenced())
197*8975f5c5SAndroid Build Coastguard Worker     {
198*8975f5c5SAndroid Build Coastguard Worker         stashQueryHelper();
199*8975f5c5SAndroid Build Coastguard Worker     }
200*8975f5c5SAndroid Build Coastguard Worker 
201*8975f5c5SAndroid Build Coastguard Worker     QueryVk *shareQuery = GetOnRenderPassStartEndShareQuery(contextVk, mType);
202*8975f5c5SAndroid Build Coastguard Worker 
203*8975f5c5SAndroid Build Coastguard Worker     if (shareQuery)
204*8975f5c5SAndroid Build Coastguard Worker     {
205*8975f5c5SAndroid Build Coastguard Worker         assignSharedQuery(shareQuery);
206*8975f5c5SAndroid Build Coastguard Worker 
207*8975f5c5SAndroid Build Coastguard Worker         // shareQuery has already started the query.
208*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
209*8975f5c5SAndroid Build Coastguard Worker     }
210*8975f5c5SAndroid Build Coastguard Worker 
211*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(allocateQuery(contextVk));
212*8975f5c5SAndroid Build Coastguard Worker     return mQueryHelper.get().beginRenderPassQuery(contextVk);
213*8975f5c5SAndroid Build Coastguard Worker }
214*8975f5c5SAndroid Build Coastguard Worker 
onRenderPassEnd(ContextVk * contextVk)215*8975f5c5SAndroid Build Coastguard Worker void QueryVk::onRenderPassEnd(ContextVk *contextVk)
216*8975f5c5SAndroid Build Coastguard Worker {
217*8975f5c5SAndroid Build Coastguard Worker     ASSERT(IsRenderPassQuery(contextVk, mType));
218*8975f5c5SAndroid Build Coastguard Worker 
219*8975f5c5SAndroid Build Coastguard Worker     QueryVk *shareQuery = GetOnRenderPassStartEndShareQuery(contextVk, mType);
220*8975f5c5SAndroid Build Coastguard Worker 
221*8975f5c5SAndroid Build Coastguard Worker     // If present, share query has already taken care of ending the query.
222*8975f5c5SAndroid Build Coastguard Worker     // The query may not be referenced if it's a transform feedback query that was never resumed due
223*8975f5c5SAndroid Build Coastguard Worker     // to transform feedback being paused when the render pass was broken.
224*8975f5c5SAndroid Build Coastguard Worker     if (shareQuery == nullptr && mQueryHelper.isReferenced())
225*8975f5c5SAndroid Build Coastguard Worker     {
226*8975f5c5SAndroid Build Coastguard Worker         mQueryHelper.get().endRenderPassQuery(contextVk);
227*8975f5c5SAndroid Build Coastguard Worker     }
228*8975f5c5SAndroid Build Coastguard Worker }
229*8975f5c5SAndroid Build Coastguard Worker 
accumulateStashedQueryResult(ContextVk * contextVk,vk::QueryResult * result)230*8975f5c5SAndroid Build Coastguard Worker angle::Result QueryVk::accumulateStashedQueryResult(ContextVk *contextVk, vk::QueryResult *result)
231*8975f5c5SAndroid Build Coastguard Worker {
232*8975f5c5SAndroid Build Coastguard Worker     for (vk::Shared<vk::QueryHelper> &query : mStashedQueryHelpers)
233*8975f5c5SAndroid Build Coastguard Worker     {
234*8975f5c5SAndroid Build Coastguard Worker         vk::QueryResult v(getQueryResultCount(contextVk));
235*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(query.get().getUint64Result(contextVk, &v));
236*8975f5c5SAndroid Build Coastguard Worker         *result += v;
237*8975f5c5SAndroid Build Coastguard Worker     }
238*8975f5c5SAndroid Build Coastguard Worker     releaseStashedQueries(contextVk);
239*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
240*8975f5c5SAndroid Build Coastguard Worker }
241*8975f5c5SAndroid Build Coastguard Worker 
setupBegin(ContextVk * contextVk)242*8975f5c5SAndroid Build Coastguard Worker angle::Result QueryVk::setupBegin(ContextVk *contextVk)
243*8975f5c5SAndroid Build Coastguard Worker {
244*8975f5c5SAndroid Build Coastguard Worker     if (IsRenderPassQuery(contextVk, mType))
245*8975f5c5SAndroid Build Coastguard Worker     {
246*8975f5c5SAndroid Build Coastguard Worker         // Clean up query helpers from the previous begin/end call on the same query.  Only
247*8975f5c5SAndroid Build Coastguard Worker         // necessary for in-render-pass queries.  The other queries can reuse query helpers as they
248*8975f5c5SAndroid Build Coastguard Worker         // are able to reset it ouside the render pass where they are recorded.
249*8975f5c5SAndroid Build Coastguard Worker         if (mQueryHelper.isReferenced())
250*8975f5c5SAndroid Build Coastguard Worker         {
251*8975f5c5SAndroid Build Coastguard Worker             releaseQueries(contextVk);
252*8975f5c5SAndroid Build Coastguard Worker         }
253*8975f5c5SAndroid Build Coastguard Worker 
254*8975f5c5SAndroid Build Coastguard Worker         // If either of TransformFeedbackPrimitivesWritten or PrimitivesGenerated queries are
255*8975f5c5SAndroid Build Coastguard Worker         // already active when the other one is begun, we have to switch to a new query helper (if
256*8975f5c5SAndroid Build Coastguard Worker         // in render pass), and have them share the query helper from here on.
257*8975f5c5SAndroid Build Coastguard Worker 
258*8975f5c5SAndroid Build Coastguard Worker         // If this is a transform feedback query, see if the other transform feedback query is
259*8975f5c5SAndroid Build Coastguard Worker         // already active.
260*8975f5c5SAndroid Build Coastguard Worker         QueryVk *shareQuery = GetShareQuery(contextVk, mType);
261*8975f5c5SAndroid Build Coastguard Worker 
262*8975f5c5SAndroid Build Coastguard Worker         // If so, make the other query stash its results and continue with a new query helper.
263*8975f5c5SAndroid Build Coastguard Worker         if (contextVk->hasActiveRenderPass())
264*8975f5c5SAndroid Build Coastguard Worker         {
265*8975f5c5SAndroid Build Coastguard Worker             if (shareQuery)
266*8975f5c5SAndroid Build Coastguard Worker             {
267*8975f5c5SAndroid Build Coastguard Worker                 // This serves the following scenario (TF = TransformFeedbackPrimitivesWritten, PG =
268*8975f5c5SAndroid Build Coastguard Worker                 // PrimitivesGenerated):
269*8975f5c5SAndroid Build Coastguard Worker                 //
270*8975f5c5SAndroid Build Coastguard Worker                 // - TF starts <-- QueryHelper1 starts
271*8975f5c5SAndroid Build Coastguard Worker                 // - Draw
272*8975f5c5SAndroid Build Coastguard Worker                 // - PG starts <-- QueryHelper1 stashed in TF, TF starts QueryHelper2,
273*8975f5c5SAndroid Build Coastguard Worker                 //                                             PG shares QueryHelper2
274*8975f5c5SAndroid Build Coastguard Worker                 // - Draw
275*8975f5c5SAndroid Build Coastguard Worker                 shareQuery->onRenderPassEnd(contextVk);
276*8975f5c5SAndroid Build Coastguard Worker                 shareQuery->stashQueryHelper();
277*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(shareQuery->allocateQuery(contextVk));
278*8975f5c5SAndroid Build Coastguard Worker 
279*8975f5c5SAndroid Build Coastguard Worker                 // Share the query helper with the other transform feedback query.  After
280*8975f5c5SAndroid Build Coastguard Worker                 // |setupBegin()| returns, they query helper is started on behalf of the shared
281*8975f5c5SAndroid Build Coastguard Worker                 // query.
282*8975f5c5SAndroid Build Coastguard Worker                 assignSharedQuery(shareQuery);
283*8975f5c5SAndroid Build Coastguard Worker             }
284*8975f5c5SAndroid Build Coastguard Worker         }
285*8975f5c5SAndroid Build Coastguard Worker         else
286*8975f5c5SAndroid Build Coastguard Worker         {
287*8975f5c5SAndroid Build Coastguard Worker             // Keep the query helper unallocated.  When the render pass starts, a new one
288*8975f5c5SAndroid Build Coastguard Worker             // will be allocated / shared.
289*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Continue;
290*8975f5c5SAndroid Build Coastguard Worker         }
291*8975f5c5SAndroid Build Coastguard Worker     }
292*8975f5c5SAndroid Build Coastguard Worker 
293*8975f5c5SAndroid Build Coastguard Worker     // If no query helper, create a new one.
294*8975f5c5SAndroid Build Coastguard Worker     if (!mQueryHelper.isReferenced())
295*8975f5c5SAndroid Build Coastguard Worker     {
296*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(allocateQuery(contextVk));
297*8975f5c5SAndroid Build Coastguard Worker     }
298*8975f5c5SAndroid Build Coastguard Worker 
299*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
300*8975f5c5SAndroid Build Coastguard Worker }
301*8975f5c5SAndroid Build Coastguard Worker 
begin(const gl::Context * context)302*8975f5c5SAndroid Build Coastguard Worker angle::Result QueryVk::begin(const gl::Context *context)
303*8975f5c5SAndroid Build Coastguard Worker {
304*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
305*8975f5c5SAndroid Build Coastguard Worker 
306*8975f5c5SAndroid Build Coastguard Worker     // Ensure that we start with the right RenderPass when we begin a new query.
307*8975f5c5SAndroid Build Coastguard Worker     if (contextVk->getState().isDrawFramebufferBindingDirty())
308*8975f5c5SAndroid Build Coastguard Worker     {
309*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(
310*8975f5c5SAndroid Build Coastguard Worker             RenderPassClosureReason::FramebufferBindingChange));
311*8975f5c5SAndroid Build Coastguard Worker     }
312*8975f5c5SAndroid Build Coastguard Worker 
313*8975f5c5SAndroid Build Coastguard Worker     mCachedResultValid = false;
314*8975f5c5SAndroid Build Coastguard Worker 
315*8975f5c5SAndroid Build Coastguard Worker     // Transform feedback query is handled by a CPU-calculated value when emulated.
316*8975f5c5SAndroid Build Coastguard Worker     if (IsEmulatedTransformFeedbackQuery(contextVk, mType))
317*8975f5c5SAndroid Build Coastguard Worker     {
318*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!contextVk->getFeatures().supportsTransformFeedbackExtension.enabled);
319*8975f5c5SAndroid Build Coastguard Worker         mTransformFeedbackPrimitivesDrawn = 0;
320*8975f5c5SAndroid Build Coastguard Worker 
321*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
322*8975f5c5SAndroid Build Coastguard Worker     }
323*8975f5c5SAndroid Build Coastguard Worker 
324*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(setupBegin(contextVk));
325*8975f5c5SAndroid Build Coastguard Worker 
326*8975f5c5SAndroid Build Coastguard Worker     switch (mType)
327*8975f5c5SAndroid Build Coastguard Worker     {
328*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::AnySamples:
329*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::AnySamplesConservative:
330*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::PrimitivesGenerated:
331*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::TransformFeedbackPrimitivesWritten:
332*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(contextVk->beginRenderPassQuery(this));
333*8975f5c5SAndroid Build Coastguard Worker             break;
334*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::Timestamp:
335*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(mQueryHelper.get().beginQuery(contextVk));
336*8975f5c5SAndroid Build Coastguard Worker             break;
337*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::TimeElapsed:
338*8975f5c5SAndroid Build Coastguard Worker             // Note: TimeElapsed is implemented by using two Timestamp queries and taking the diff.
339*8975f5c5SAndroid Build Coastguard Worker             if (!mQueryHelperTimeElapsedBegin.valid())
340*8975f5c5SAndroid Build Coastguard Worker             {
341*8975f5c5SAndroid Build Coastguard Worker                 // Note that timestamp queries are not allowed with multiview, so query count is
342*8975f5c5SAndroid Build Coastguard Worker                 // always 1.
343*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(contextVk->getQueryPool(mType)->allocateQuery(
344*8975f5c5SAndroid Build Coastguard Worker                     contextVk, &mQueryHelperTimeElapsedBegin, 1));
345*8975f5c5SAndroid Build Coastguard Worker             }
346*8975f5c5SAndroid Build Coastguard Worker 
347*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(mQueryHelperTimeElapsedBegin.flushAndWriteTimestamp(contextVk));
348*8975f5c5SAndroid Build Coastguard Worker             break;
349*8975f5c5SAndroid Build Coastguard Worker         default:
350*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
351*8975f5c5SAndroid Build Coastguard Worker             break;
352*8975f5c5SAndroid Build Coastguard Worker     }
353*8975f5c5SAndroid Build Coastguard Worker 
354*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
355*8975f5c5SAndroid Build Coastguard Worker }
356*8975f5c5SAndroid Build Coastguard Worker 
end(const gl::Context * context)357*8975f5c5SAndroid Build Coastguard Worker angle::Result QueryVk::end(const gl::Context *context)
358*8975f5c5SAndroid Build Coastguard Worker {
359*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
360*8975f5c5SAndroid Build Coastguard Worker 
361*8975f5c5SAndroid Build Coastguard Worker     // Transform feedback query is handled by a CPU-calculated value when emulated.
362*8975f5c5SAndroid Build Coastguard Worker     if (IsEmulatedTransformFeedbackQuery(contextVk, mType))
363*8975f5c5SAndroid Build Coastguard Worker     {
364*8975f5c5SAndroid Build Coastguard Worker         ASSERT(contextVk->getFeatures().emulateTransformFeedback.enabled);
365*8975f5c5SAndroid Build Coastguard Worker         mCachedResult = mTransformFeedbackPrimitivesDrawn;
366*8975f5c5SAndroid Build Coastguard Worker 
367*8975f5c5SAndroid Build Coastguard Worker         // There could be transform feedback in progress, so add the primitives drawn so far
368*8975f5c5SAndroid Build Coastguard Worker         // from the current transform feedback object.
369*8975f5c5SAndroid Build Coastguard Worker         gl::TransformFeedback *transformFeedback =
370*8975f5c5SAndroid Build Coastguard Worker             context->getState().getCurrentTransformFeedback();
371*8975f5c5SAndroid Build Coastguard Worker         if (transformFeedback)
372*8975f5c5SAndroid Build Coastguard Worker         {
373*8975f5c5SAndroid Build Coastguard Worker             mCachedResult += transformFeedback->getPrimitivesDrawn();
374*8975f5c5SAndroid Build Coastguard Worker         }
375*8975f5c5SAndroid Build Coastguard Worker         mCachedResultValid = true;
376*8975f5c5SAndroid Build Coastguard Worker 
377*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
378*8975f5c5SAndroid Build Coastguard Worker     }
379*8975f5c5SAndroid Build Coastguard Worker 
380*8975f5c5SAndroid Build Coastguard Worker     switch (mType)
381*8975f5c5SAndroid Build Coastguard Worker     {
382*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::AnySamples:
383*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::AnySamplesConservative:
384*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::PrimitivesGenerated:
385*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::TransformFeedbackPrimitivesWritten:
386*8975f5c5SAndroid Build Coastguard Worker         {
387*8975f5c5SAndroid Build Coastguard Worker             QueryVk *shareQuery = GetShareQuery(contextVk, mType);
388*8975f5c5SAndroid Build Coastguard Worker             ASSERT(shareQuery == nullptr || &mQueryHelper.get() == &shareQuery->mQueryHelper.get());
389*8975f5c5SAndroid Build Coastguard Worker 
390*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(contextVk->endRenderPassQuery(this));
391*8975f5c5SAndroid Build Coastguard Worker 
392*8975f5c5SAndroid Build Coastguard Worker             // If another query shares its query helper with this one, its query has just ended!
393*8975f5c5SAndroid Build Coastguard Worker             // Make it stash its query and create a new one so it can continue.
394*8975f5c5SAndroid Build Coastguard Worker             if (shareQuery && shareQuery->mQueryHelper.isReferenced())
395*8975f5c5SAndroid Build Coastguard Worker             {
396*8975f5c5SAndroid Build Coastguard Worker                 // This serves the following scenario (TF = TransformFeedbackPrimitivesWritten, PG =
397*8975f5c5SAndroid Build Coastguard Worker                 // PrimitivesGenerated):
398*8975f5c5SAndroid Build Coastguard Worker                 //
399*8975f5c5SAndroid Build Coastguard Worker                 // - TF starts <-- QueryHelper1 starts
400*8975f5c5SAndroid Build Coastguard Worker                 // - PG starts <-- PG shares QueryHelper1
401*8975f5c5SAndroid Build Coastguard Worker                 // - Draw
402*8975f5c5SAndroid Build Coastguard Worker                 // - TF ends   <-- Results = QueryHelper1,
403*8975f5c5SAndroid Build Coastguard Worker                 //                 QueryHelper1 stashed in PG, PG starts QueryHelper2
404*8975f5c5SAndroid Build Coastguard Worker                 // - Draw
405*8975f5c5SAndroid Build Coastguard Worker                 // - PG ends   <-- Results = QueryHelper1 + QueryHelper2
406*8975f5c5SAndroid Build Coastguard Worker                 if (contextVk->hasActiveRenderPass())
407*8975f5c5SAndroid Build Coastguard Worker                 {
408*8975f5c5SAndroid Build Coastguard Worker                     ANGLE_TRY(shareQuery->onRenderPassStart(contextVk));
409*8975f5c5SAndroid Build Coastguard Worker                 }
410*8975f5c5SAndroid Build Coastguard Worker             }
411*8975f5c5SAndroid Build Coastguard Worker             break;
412*8975f5c5SAndroid Build Coastguard Worker         }
413*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::Timestamp:
414*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(mQueryHelper.get().endQuery(contextVk));
415*8975f5c5SAndroid Build Coastguard Worker             break;
416*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::TimeElapsed:
417*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(mQueryHelper.get().flushAndWriteTimestamp(contextVk));
418*8975f5c5SAndroid Build Coastguard Worker             break;
419*8975f5c5SAndroid Build Coastguard Worker         default:
420*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
421*8975f5c5SAndroid Build Coastguard Worker             break;
422*8975f5c5SAndroid Build Coastguard Worker     }
423*8975f5c5SAndroid Build Coastguard Worker 
424*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
425*8975f5c5SAndroid Build Coastguard Worker }
426*8975f5c5SAndroid Build Coastguard Worker 
queryCounter(const gl::Context * context)427*8975f5c5SAndroid Build Coastguard Worker angle::Result QueryVk::queryCounter(const gl::Context *context)
428*8975f5c5SAndroid Build Coastguard Worker {
429*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mType == gl::QueryType::Timestamp);
430*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
431*8975f5c5SAndroid Build Coastguard Worker 
432*8975f5c5SAndroid Build Coastguard Worker     mCachedResultValid = false;
433*8975f5c5SAndroid Build Coastguard Worker 
434*8975f5c5SAndroid Build Coastguard Worker     if (!mQueryHelper.isReferenced())
435*8975f5c5SAndroid Build Coastguard Worker     {
436*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(allocateQuery(contextVk));
437*8975f5c5SAndroid Build Coastguard Worker     }
438*8975f5c5SAndroid Build Coastguard Worker 
439*8975f5c5SAndroid Build Coastguard Worker     return mQueryHelper.get().flushAndWriteTimestamp(contextVk);
440*8975f5c5SAndroid Build Coastguard Worker }
441*8975f5c5SAndroid Build Coastguard Worker 
isCurrentlyInUse(vk::Renderer * renderer) const442*8975f5c5SAndroid Build Coastguard Worker bool QueryVk::isCurrentlyInUse(vk::Renderer *renderer) const
443*8975f5c5SAndroid Build Coastguard Worker {
444*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mQueryHelper.isReferenced());
445*8975f5c5SAndroid Build Coastguard Worker     return !renderer->hasResourceUseFinished(mQueryHelper.get().getResourceUse());
446*8975f5c5SAndroid Build Coastguard Worker }
447*8975f5c5SAndroid Build Coastguard Worker 
finishRunningCommands(ContextVk * contextVk)448*8975f5c5SAndroid Build Coastguard Worker angle::Result QueryVk::finishRunningCommands(ContextVk *contextVk)
449*8975f5c5SAndroid Build Coastguard Worker {
450*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = contextVk->getRenderer();
451*8975f5c5SAndroid Build Coastguard Worker 
452*8975f5c5SAndroid Build Coastguard Worker     // Caller already made sure query has been submitted.
453*8975f5c5SAndroid Build Coastguard Worker     if (!renderer->hasResourceUseFinished(mQueryHelper.get().getResourceUse()))
454*8975f5c5SAndroid Build Coastguard Worker     {
455*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(renderer->finishResourceUse(contextVk, mQueryHelper.get().getResourceUse()));
456*8975f5c5SAndroid Build Coastguard Worker     }
457*8975f5c5SAndroid Build Coastguard Worker 
458*8975f5c5SAndroid Build Coastguard Worker     // Since mStashedQueryHelpers are older than mQueryHelper, these must also finished.
459*8975f5c5SAndroid Build Coastguard Worker     for (vk::Shared<vk::QueryHelper> &query : mStashedQueryHelpers)
460*8975f5c5SAndroid Build Coastguard Worker     {
461*8975f5c5SAndroid Build Coastguard Worker         ASSERT(renderer->hasResourceUseFinished(query.get().getResourceUse()));
462*8975f5c5SAndroid Build Coastguard Worker     }
463*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
464*8975f5c5SAndroid Build Coastguard Worker }
465*8975f5c5SAndroid Build Coastguard Worker 
getResult(const gl::Context * context,bool wait)466*8975f5c5SAndroid Build Coastguard Worker angle::Result QueryVk::getResult(const gl::Context *context, bool wait)
467*8975f5c5SAndroid Build Coastguard Worker {
468*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRACE_EVENT0("gpu.angle", "QueryVk::getResult");
469*8975f5c5SAndroid Build Coastguard Worker 
470*8975f5c5SAndroid Build Coastguard Worker     if (mCachedResultValid)
471*8975f5c5SAndroid Build Coastguard Worker     {
472*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
473*8975f5c5SAndroid Build Coastguard Worker     }
474*8975f5c5SAndroid Build Coastguard Worker 
475*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk   = vk::GetImpl(context);
476*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = contextVk->getRenderer();
477*8975f5c5SAndroid Build Coastguard Worker 
478*8975f5c5SAndroid Build Coastguard Worker     // Support the pathological case where begin/end is called on a render pass query but without
479*8975f5c5SAndroid Build Coastguard Worker     // any render passes in between.  In this case, the query helper is never allocated.
480*8975f5c5SAndroid Build Coastguard Worker     if (!mQueryHelper.isReferenced())
481*8975f5c5SAndroid Build Coastguard Worker     {
482*8975f5c5SAndroid Build Coastguard Worker         ASSERT(IsRenderPassQuery(contextVk, mType));
483*8975f5c5SAndroid Build Coastguard Worker         mCachedResult      = 0;
484*8975f5c5SAndroid Build Coastguard Worker         mCachedResultValid = true;
485*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
486*8975f5c5SAndroid Build Coastguard Worker     }
487*8975f5c5SAndroid Build Coastguard Worker 
488*8975f5c5SAndroid Build Coastguard Worker     // glGetQueryObject* requires an implicit flush of the command buffers to guarantee execution in
489*8975f5c5SAndroid Build Coastguard Worker     // finite time.
490*8975f5c5SAndroid Build Coastguard Worker     // Note regarding time-elapsed: end should have been called after begin, so flushing when end
491*8975f5c5SAndroid Build Coastguard Worker     // has pending work should flush begin too.
492*8975f5c5SAndroid Build Coastguard Worker     // We only need to check mQueryHelper, not mStashedQueryHelper, since they are always in order.
493*8975f5c5SAndroid Build Coastguard Worker     if (contextVk->hasUnsubmittedUse(mQueryHelper.get()))
494*8975f5c5SAndroid Build Coastguard Worker     {
495*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(contextVk->flushAndSubmitCommands(nullptr, nullptr,
496*8975f5c5SAndroid Build Coastguard Worker                                                     RenderPassClosureReason::GetQueryResult));
497*8975f5c5SAndroid Build Coastguard Worker 
498*8975f5c5SAndroid Build Coastguard Worker         ASSERT(contextVk->getRenderer()->hasResourceUseSubmitted(
499*8975f5c5SAndroid Build Coastguard Worker             mQueryHelperTimeElapsedBegin.getResourceUse()));
500*8975f5c5SAndroid Build Coastguard Worker         ASSERT(
501*8975f5c5SAndroid Build Coastguard Worker             contextVk->getRenderer()->hasResourceUseSubmitted(mQueryHelper.get().getResourceUse()));
502*8975f5c5SAndroid Build Coastguard Worker     }
503*8975f5c5SAndroid Build Coastguard Worker 
504*8975f5c5SAndroid Build Coastguard Worker     // If the command buffer this query is being written to is still in flight and uses
505*8975f5c5SAndroid Build Coastguard Worker     // vkCmdResetQueryPool, its reset command may not have been performed by the GPU yet.  To avoid
506*8975f5c5SAndroid Build Coastguard Worker     // a race condition in this case, wait for the batch to finish first before querying (or return
507*8975f5c5SAndroid Build Coastguard Worker     // not-ready if not waiting).
508*8975f5c5SAndroid Build Coastguard Worker     if (isCurrentlyInUse(renderer) &&
509*8975f5c5SAndroid Build Coastguard Worker         (!renderer->getFeatures().supportsHostQueryReset.enabled ||
510*8975f5c5SAndroid Build Coastguard Worker          renderer->getFeatures().forceWaitForSubmissionToCompleteForQueryResult.enabled ||
511*8975f5c5SAndroid Build Coastguard Worker          renderer->isAsyncCommandQueueEnabled()))
512*8975f5c5SAndroid Build Coastguard Worker     {
513*8975f5c5SAndroid Build Coastguard Worker         // The query might appear busy because there was no check for completed commands
514*8975f5c5SAndroid Build Coastguard Worker         // recently. Do that now and see if the query is still busy.  If the application is
515*8975f5c5SAndroid Build Coastguard Worker         // looping until the query results become available, there wouldn't be any forward
516*8975f5c5SAndroid Build Coastguard Worker         // progress without this.
517*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(renderer->checkCompletedCommandsAndCleanup(contextVk));
518*8975f5c5SAndroid Build Coastguard Worker 
519*8975f5c5SAndroid Build Coastguard Worker         if (isCurrentlyInUse(renderer))
520*8975f5c5SAndroid Build Coastguard Worker         {
521*8975f5c5SAndroid Build Coastguard Worker             if (!wait)
522*8975f5c5SAndroid Build Coastguard Worker             {
523*8975f5c5SAndroid Build Coastguard Worker                 return angle::Result::Continue;
524*8975f5c5SAndroid Build Coastguard Worker             }
525*8975f5c5SAndroid Build Coastguard Worker             ANGLE_VK_PERF_WARNING(contextVk, GL_DEBUG_SEVERITY_HIGH,
526*8975f5c5SAndroid Build Coastguard Worker                                   "GPU stall due to waiting on uncompleted query");
527*8975f5c5SAndroid Build Coastguard Worker 
528*8975f5c5SAndroid Build Coastguard Worker             // Assert that the work has been sent to the GPU
529*8975f5c5SAndroid Build Coastguard Worker             ASSERT(!contextVk->hasUnsubmittedUse(mQueryHelper.get()));
530*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(finishRunningCommands(contextVk));
531*8975f5c5SAndroid Build Coastguard Worker         }
532*8975f5c5SAndroid Build Coastguard Worker     }
533*8975f5c5SAndroid Build Coastguard Worker 
534*8975f5c5SAndroid Build Coastguard Worker     // If its a render pass query, the current query helper must have commands recorded (i.e. it's
535*8975f5c5SAndroid Build Coastguard Worker     // not a newly allocated query with the actual queries all stashed).  If this is not respected
536*8975f5c5SAndroid Build Coastguard Worker     // and !wait, |mQueryHelper.get().getUint64ResultNonBlocking()| will tell that the result is
537*8975f5c5SAndroid Build Coastguard Worker     // readily available, which may not be true.  The subsequent calls to |getUint64Result()| on the
538*8975f5c5SAndroid Build Coastguard Worker     // stashed queries will incur a wait that is not desired by the application.
539*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!IsRenderPassQuery(contextVk, mType) || mQueryHelper.get().hasSubmittedCommands());
540*8975f5c5SAndroid Build Coastguard Worker 
541*8975f5c5SAndroid Build Coastguard Worker     vk::QueryResult result(getQueryResultCount(contextVk));
542*8975f5c5SAndroid Build Coastguard Worker 
543*8975f5c5SAndroid Build Coastguard Worker     if (wait)
544*8975f5c5SAndroid Build Coastguard Worker     {
545*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mQueryHelper.get().getUint64Result(contextVk, &result));
546*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(accumulateStashedQueryResult(contextVk, &result));
547*8975f5c5SAndroid Build Coastguard Worker     }
548*8975f5c5SAndroid Build Coastguard Worker     else
549*8975f5c5SAndroid Build Coastguard Worker     {
550*8975f5c5SAndroid Build Coastguard Worker         bool available = false;
551*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mQueryHelper.get().getUint64ResultNonBlocking(contextVk, &result, &available));
552*8975f5c5SAndroid Build Coastguard Worker         if (!available)
553*8975f5c5SAndroid Build Coastguard Worker         {
554*8975f5c5SAndroid Build Coastguard Worker             // If the results are not ready, do nothing.  mCachedResultValid remains false.
555*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Continue;
556*8975f5c5SAndroid Build Coastguard Worker         }
557*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(accumulateStashedQueryResult(contextVk, &result));
558*8975f5c5SAndroid Build Coastguard Worker     }
559*8975f5c5SAndroid Build Coastguard Worker 
560*8975f5c5SAndroid Build Coastguard Worker     double timestampPeriod = renderer->getPhysicalDeviceProperties().limits.timestampPeriod;
561*8975f5c5SAndroid Build Coastguard Worker 
562*8975f5c5SAndroid Build Coastguard Worker     // Fix up the results to what OpenGL expects.
563*8975f5c5SAndroid Build Coastguard Worker     switch (mType)
564*8975f5c5SAndroid Build Coastguard Worker     {
565*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::AnySamples:
566*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::AnySamplesConservative:
567*8975f5c5SAndroid Build Coastguard Worker             // OpenGL query result in these cases is binary
568*8975f5c5SAndroid Build Coastguard Worker             mCachedResult = !!result.getResult(vk::QueryResult::kDefaultResultIndex);
569*8975f5c5SAndroid Build Coastguard Worker             break;
570*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::Timestamp:
571*8975f5c5SAndroid Build Coastguard Worker             mCachedResult = static_cast<uint64_t>(
572*8975f5c5SAndroid Build Coastguard Worker                 result.getResult(vk::QueryResult::kDefaultResultIndex) * timestampPeriod);
573*8975f5c5SAndroid Build Coastguard Worker             break;
574*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::TimeElapsed:
575*8975f5c5SAndroid Build Coastguard Worker         {
576*8975f5c5SAndroid Build Coastguard Worker             vk::QueryResult timeElapsedBegin(1);
577*8975f5c5SAndroid Build Coastguard Worker 
578*8975f5c5SAndroid Build Coastguard Worker             // Since the result of the end query of time-elapsed is already available, the
579*8975f5c5SAndroid Build Coastguard Worker             // result of begin query must be available too.
580*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(mQueryHelperTimeElapsedBegin.getUint64Result(contextVk, &timeElapsedBegin));
581*8975f5c5SAndroid Build Coastguard Worker 
582*8975f5c5SAndroid Build Coastguard Worker             uint64_t delta = result.getResult(vk::QueryResult::kDefaultResultIndex) -
583*8975f5c5SAndroid Build Coastguard Worker                              timeElapsedBegin.getResult(vk::QueryResult::kDefaultResultIndex);
584*8975f5c5SAndroid Build Coastguard Worker             mCachedResult = static_cast<uint64_t>(delta * timestampPeriod);
585*8975f5c5SAndroid Build Coastguard Worker             break;
586*8975f5c5SAndroid Build Coastguard Worker         }
587*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::TransformFeedbackPrimitivesWritten:
588*8975f5c5SAndroid Build Coastguard Worker             mCachedResult =
589*8975f5c5SAndroid Build Coastguard Worker                 result.getResult(IsPrimitivesGeneratedQueryShared(contextVk)
590*8975f5c5SAndroid Build Coastguard Worker                                      ? vk::QueryResult::kTransformFeedbackPrimitivesWrittenIndex
591*8975f5c5SAndroid Build Coastguard Worker                                      : vk::QueryResult::kDefaultResultIndex);
592*8975f5c5SAndroid Build Coastguard Worker             break;
593*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::PrimitivesGenerated:
594*8975f5c5SAndroid Build Coastguard Worker             mCachedResult = result.getResult(IsPrimitivesGeneratedQueryShared(contextVk)
595*8975f5c5SAndroid Build Coastguard Worker                                                  ? vk::QueryResult::kPrimitivesGeneratedIndex
596*8975f5c5SAndroid Build Coastguard Worker                                                  : vk::QueryResult::kDefaultResultIndex);
597*8975f5c5SAndroid Build Coastguard Worker             break;
598*8975f5c5SAndroid Build Coastguard Worker         default:
599*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
600*8975f5c5SAndroid Build Coastguard Worker             break;
601*8975f5c5SAndroid Build Coastguard Worker     }
602*8975f5c5SAndroid Build Coastguard Worker 
603*8975f5c5SAndroid Build Coastguard Worker     mCachedResultValid = true;
604*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
605*8975f5c5SAndroid Build Coastguard Worker }
getResult(const gl::Context * context,GLint * params)606*8975f5c5SAndroid Build Coastguard Worker angle::Result QueryVk::getResult(const gl::Context *context, GLint *params)
607*8975f5c5SAndroid Build Coastguard Worker {
608*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(getResult(context, true));
609*8975f5c5SAndroid Build Coastguard Worker     *params = static_cast<GLint>(mCachedResult);
610*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
611*8975f5c5SAndroid Build Coastguard Worker }
612*8975f5c5SAndroid Build Coastguard Worker 
getResult(const gl::Context * context,GLuint * params)613*8975f5c5SAndroid Build Coastguard Worker angle::Result QueryVk::getResult(const gl::Context *context, GLuint *params)
614*8975f5c5SAndroid Build Coastguard Worker {
615*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(getResult(context, true));
616*8975f5c5SAndroid Build Coastguard Worker     *params = static_cast<GLuint>(mCachedResult);
617*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
618*8975f5c5SAndroid Build Coastguard Worker }
619*8975f5c5SAndroid Build Coastguard Worker 
getResult(const gl::Context * context,GLint64 * params)620*8975f5c5SAndroid Build Coastguard Worker angle::Result QueryVk::getResult(const gl::Context *context, GLint64 *params)
621*8975f5c5SAndroid Build Coastguard Worker {
622*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(getResult(context, true));
623*8975f5c5SAndroid Build Coastguard Worker     *params = static_cast<GLint64>(mCachedResult);
624*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
625*8975f5c5SAndroid Build Coastguard Worker }
626*8975f5c5SAndroid Build Coastguard Worker 
getResult(const gl::Context * context,GLuint64 * params)627*8975f5c5SAndroid Build Coastguard Worker angle::Result QueryVk::getResult(const gl::Context *context, GLuint64 *params)
628*8975f5c5SAndroid Build Coastguard Worker {
629*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(getResult(context, true));
630*8975f5c5SAndroid Build Coastguard Worker     *params = mCachedResult;
631*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
632*8975f5c5SAndroid Build Coastguard Worker }
633*8975f5c5SAndroid Build Coastguard Worker 
isResultAvailable(const gl::Context * context,bool * available)634*8975f5c5SAndroid Build Coastguard Worker angle::Result QueryVk::isResultAvailable(const gl::Context *context, bool *available)
635*8975f5c5SAndroid Build Coastguard Worker {
636*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(getResult(context, false));
637*8975f5c5SAndroid Build Coastguard Worker     *available = mCachedResultValid;
638*8975f5c5SAndroid Build Coastguard Worker 
639*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
640*8975f5c5SAndroid Build Coastguard Worker }
641*8975f5c5SAndroid Build Coastguard Worker 
onTransformFeedbackEnd(GLsizeiptr primitivesDrawn)642*8975f5c5SAndroid Build Coastguard Worker void QueryVk::onTransformFeedbackEnd(GLsizeiptr primitivesDrawn)
643*8975f5c5SAndroid Build Coastguard Worker {
644*8975f5c5SAndroid Build Coastguard Worker     mTransformFeedbackPrimitivesDrawn += primitivesDrawn;
645*8975f5c5SAndroid Build Coastguard Worker }
646*8975f5c5SAndroid Build Coastguard Worker 
getQueryResultCount(ContextVk * contextVk) const647*8975f5c5SAndroid Build Coastguard Worker uint32_t QueryVk::getQueryResultCount(ContextVk *contextVk) const
648*8975f5c5SAndroid Build Coastguard Worker {
649*8975f5c5SAndroid Build Coastguard Worker     switch (mType)
650*8975f5c5SAndroid Build Coastguard Worker     {
651*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::PrimitivesGenerated:
652*8975f5c5SAndroid Build Coastguard Worker             return IsPrimitivesGeneratedQueryShared(contextVk) ? 2 : 1;
653*8975f5c5SAndroid Build Coastguard Worker         case gl::QueryType::TransformFeedbackPrimitivesWritten:
654*8975f5c5SAndroid Build Coastguard Worker             return 2;
655*8975f5c5SAndroid Build Coastguard Worker         default:
656*8975f5c5SAndroid Build Coastguard Worker             return 1;
657*8975f5c5SAndroid Build Coastguard Worker     }
658*8975f5c5SAndroid Build Coastguard Worker }
659*8975f5c5SAndroid Build Coastguard Worker }  // namespace rx
660