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