blob: d6467fb4c97ef8c2b536f2e423d0ca30b88560e0 [file] [log] [blame]
Jamie Madill9e54b5a2016-05-25 12:57:39 -04001//
Shahbaz Youssefi563fbaa2018-10-02 11:22:01 -04002// Copyright 2016-2018 The ANGLE Project Authors. All rights reserved.
Jamie Madill9e54b5a2016-05-25 12:57:39 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6// QueryVk.cpp:
7// Implements the class methods for QueryVk.
8//
9
10#include "libANGLE/renderer/vulkan/QueryVk.h"
Shahbaz Youssefi563fbaa2018-10-02 11:22:01 -040011#include "libANGLE/Context.h"
12#include "libANGLE/renderer/vulkan/ContextVk.h"
Shahbaz Youssefic4765aa2018-10-12 14:40:29 -040013#include "libANGLE/renderer/vulkan/RendererVk.h"
Jamie Madill9e54b5a2016-05-25 12:57:39 -040014
15#include "common/debug.h"
16
17namespace rx
18{
19
Shahbaz Youssefi563fbaa2018-10-02 11:22:01 -040020QueryVk::QueryVk(gl::QueryType type) : QueryImpl(type), mCachedResult(0), mCachedResultValid(false)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040021{
22}
23
Shahbaz Youssefi563fbaa2018-10-02 11:22:01 -040024QueryVk::~QueryVk() = default;
25
26gl::Error QueryVk::onDestroy(const gl::Context *context)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040027{
Shahbaz Youssefi563fbaa2018-10-02 11:22:01 -040028 ContextVk *contextVk = vk::GetImpl(context);
29 contextVk->getQueryPool(getType())->freeQuery(contextVk, &mQueryHelper);
Shahbaz Youssefic2b576d2018-10-12 14:45:34 -040030 contextVk->getQueryPool(getType())->freeQuery(contextVk, &mQueryHelperTimeElapsedBegin);
Shahbaz Youssefi563fbaa2018-10-02 11:22:01 -040031
32 return gl::NoError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -040033}
34
Jamie Madill5188a272018-07-25 10:53:56 -040035gl::Error QueryVk::begin(const gl::Context *context)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040036{
Shahbaz Youssefi563fbaa2018-10-02 11:22:01 -040037 ContextVk *contextVk = vk::GetImpl(context);
38
Shahbaz Youssefi563fbaa2018-10-02 11:22:01 -040039 mCachedResultValid = false;
40
Shahbaz Youssefic2b576d2018-10-12 14:45:34 -040041 if (!mQueryHelper.getQueryPool())
42 {
43 ANGLE_TRY(contextVk->getQueryPool(getType())->allocateQuery(contextVk, &mQueryHelper));
44 }
45
46 // Note: TimeElapsed is implemented by using two Timestamp queries and taking the diff.
47 if (getType() == gl::QueryType::TimeElapsed)
48 {
49 if (!mQueryHelperTimeElapsedBegin.getQueryPool())
50 {
51 ANGLE_TRY(contextVk->getQueryPool(getType())->allocateQuery(
52 contextVk, &mQueryHelperTimeElapsedBegin));
53 }
54
55 mQueryHelperTimeElapsedBegin.writeTimestamp(contextVk,
56 mQueryHelperTimeElapsedBegin.getQueryPool(),
57 mQueryHelperTimeElapsedBegin.getQuery());
58 }
59 else
60 {
61 mQueryHelper.beginQuery(contextVk, mQueryHelper.getQueryPool(), mQueryHelper.getQuery());
62 }
Shahbaz Youssefi563fbaa2018-10-02 11:22:01 -040063
64 return gl::NoError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -040065}
66
Jamie Madill5188a272018-07-25 10:53:56 -040067gl::Error QueryVk::end(const gl::Context *context)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040068{
Shahbaz Youssefi563fbaa2018-10-02 11:22:01 -040069 ContextVk *contextVk = vk::GetImpl(context);
70
Shahbaz Youssefic2b576d2018-10-12 14:45:34 -040071 if (getType() == gl::QueryType::TimeElapsed)
72 {
73 mQueryHelper.writeTimestamp(contextVk, mQueryHelper.getQueryPool(),
74 mQueryHelper.getQuery());
75 }
76 else
77 {
78 mQueryHelper.endQuery(contextVk, mQueryHelper.getQueryPool(), mQueryHelper.getQuery());
79 }
Shahbaz Youssefi563fbaa2018-10-02 11:22:01 -040080
81 return gl::NoError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -040082}
83
Jamie Madill5188a272018-07-25 10:53:56 -040084gl::Error QueryVk::queryCounter(const gl::Context *context)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040085{
Shahbaz Youssefic2b576d2018-10-12 14:45:34 -040086 ContextVk *contextVk = vk::GetImpl(context);
87
88 mCachedResultValid = false;
89
90 if (!mQueryHelper.getQueryPool())
91 {
92 ANGLE_TRY(contextVk->getQueryPool(getType())->allocateQuery(contextVk, &mQueryHelper));
93 }
94
95 ASSERT(getType() == gl::QueryType::Timestamp);
96
97 mQueryHelper.writeTimestamp(contextVk, mQueryHelper.getQueryPool(), mQueryHelper.getQuery());
98
99 return gl::NoError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400100}
101
Shahbaz Youssefi563fbaa2018-10-02 11:22:01 -0400102angle::Result QueryVk::getResult(const gl::Context *context, bool wait)
103{
104 if (mCachedResultValid)
105 {
106 return angle::Result::Continue();
107 }
108
109 ContextVk *contextVk = vk::GetImpl(context);
Shahbaz Youssefic4765aa2018-10-12 14:40:29 -0400110 RendererVk *renderer = contextVk->getRenderer();
111
112 // glGetQueryObject* requires an implicit flush of the command buffers to guarantee execution in
113 // finite time.
Shahbaz Youssefic2b576d2018-10-12 14:45:34 -0400114 // Note regarding time-elapsed: end should have been called after begin, so flushing when end
115 // has pending work should flush begin too.
Shahbaz Youssefic4765aa2018-10-12 14:40:29 -0400116 if (mQueryHelper.hasPendingWork(renderer))
117 {
118 ANGLE_TRY_HANDLE(context, renderer->flush(contextVk));
Shahbaz Youssefic2b576d2018-10-12 14:45:34 -0400119
120 ASSERT(!mQueryHelperTimeElapsedBegin.hasPendingWork(renderer));
Shahbaz Youssefic4765aa2018-10-12 14:40:29 -0400121 ASSERT(!mQueryHelper.hasPendingWork(renderer));
122 }
123
124 // If the command buffer this query is being written to is still in flight, its reset command
125 // may not have been performed by the GPU yet. To avoid a race condition in this case, wait
126 // for the batch to finish first before querying (or return not-ready if not waiting).
127 ANGLE_TRY(renderer->checkCompletedCommands(contextVk));
128 if (mQueryHelper.isResourceInUse(renderer))
129 {
130 if (!wait)
131 {
132 return angle::Result::Continue();
133 }
134 ANGLE_TRY(renderer->finishToSerial(contextVk, mQueryHelper.getStoredQueueSerial()));
135 }
Shahbaz Youssefi563fbaa2018-10-02 11:22:01 -0400136
137 VkQueryResultFlags flags = (wait ? VK_QUERY_RESULT_WAIT_BIT : 0) | VK_QUERY_RESULT_64_BIT;
138
139 angle::Result result = mQueryHelper.getQueryPool()->getResults(
140 contextVk, mQueryHelper.getQuery(), 1, sizeof(mCachedResult), &mCachedResult,
141 sizeof(mCachedResult), flags);
142 ANGLE_TRY(result);
143
Shahbaz Youssefic4765aa2018-10-12 14:40:29 -0400144 // If the results are not ready, do nothing. mCachedResultValid remains false.
145 if (result == angle::Result::Incomplete())
Shahbaz Youssefi563fbaa2018-10-02 11:22:01 -0400146 {
Shahbaz Youssefic4765aa2018-10-12 14:40:29 -0400147 // If VK_QUERY_RESULT_WAIT_BIT was given, Incomplete() cannot have been returned.
148 ASSERT(!wait);
149 return angle::Result::Continue();
Shahbaz Youssefi563fbaa2018-10-02 11:22:01 -0400150 }
151
Shahbaz Youssefic4765aa2018-10-12 14:40:29 -0400152 // Fix up the results to what OpenGL expects.
153 switch (getType())
154 {
155 case gl::QueryType::AnySamples:
156 case gl::QueryType::AnySamplesConservative:
157 // OpenGL query result in these cases is binary
158 mCachedResult = !!mCachedResult;
159 break;
Shahbaz Youssefic2b576d2018-10-12 14:45:34 -0400160 case gl::QueryType::Timestamp:
161 break;
162 case gl::QueryType::TimeElapsed:
163 {
164 uint64_t timeElapsedEnd = mCachedResult;
165
166 result = mQueryHelperTimeElapsedBegin.getQueryPool()->getResults(
167 contextVk, mQueryHelperTimeElapsedBegin.getQuery(), 1, sizeof(mCachedResult),
168 &mCachedResult, sizeof(mCachedResult), flags);
169 ANGLE_TRY(result);
170
171 // Since the result of the end query of time-elapsed is already available, the
172 // result of begin query must be available too.
173 ASSERT(result != angle::Result::Incomplete());
174
175 mCachedResult = timeElapsedEnd - mCachedResult;
176 break;
177 }
Shahbaz Youssefic4765aa2018-10-12 14:40:29 -0400178 default:
179 UNREACHABLE();
180 break;
181 }
182
183 mCachedResultValid = true;
Shahbaz Youssefi563fbaa2018-10-02 11:22:01 -0400184 return angle::Result::Continue();
185}
Jamie Madill5188a272018-07-25 10:53:56 -0400186gl::Error QueryVk::getResult(const gl::Context *context, GLint *params)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400187{
Shahbaz Youssefi563fbaa2018-10-02 11:22:01 -0400188 ANGLE_TRY(getResult(context, true));
189 *params = static_cast<GLint>(mCachedResult);
190 return gl::NoError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400191}
192
Jamie Madill5188a272018-07-25 10:53:56 -0400193gl::Error QueryVk::getResult(const gl::Context *context, GLuint *params)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400194{
Shahbaz Youssefi563fbaa2018-10-02 11:22:01 -0400195 ANGLE_TRY(getResult(context, true));
196 *params = static_cast<GLuint>(mCachedResult);
197 return gl::NoError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400198}
199
Jamie Madill5188a272018-07-25 10:53:56 -0400200gl::Error QueryVk::getResult(const gl::Context *context, GLint64 *params)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400201{
Shahbaz Youssefi563fbaa2018-10-02 11:22:01 -0400202 ANGLE_TRY(getResult(context, true));
203 *params = static_cast<GLint64>(mCachedResult);
204 return gl::NoError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400205}
206
Jamie Madill5188a272018-07-25 10:53:56 -0400207gl::Error QueryVk::getResult(const gl::Context *context, GLuint64 *params)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400208{
Shahbaz Youssefi563fbaa2018-10-02 11:22:01 -0400209 ANGLE_TRY(getResult(context, true));
210 *params = mCachedResult;
211 return gl::NoError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400212}
213
Jamie Madill5188a272018-07-25 10:53:56 -0400214gl::Error QueryVk::isResultAvailable(const gl::Context *context, bool *available)
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400215{
Shahbaz Youssefi563fbaa2018-10-02 11:22:01 -0400216 ANGLE_TRY(getResult(context, false));
217 *available = mCachedResultValid;
218
219 return gl::NoError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400220}
221
222} // namespace rx