blob: d6e11df72b9fdee1bb79edf6f28f6f49c5889097 [file] [log] [blame]
//
// Copyright 2016-2018 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// QueryVk.cpp:
// Implements the class methods for QueryVk.
//
#include "libANGLE/renderer/vulkan/QueryVk.h"
#include "libANGLE/Context.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
#include "common/debug.h"
namespace rx
{
QueryVk::QueryVk(gl::QueryType type) : QueryImpl(type), mCachedResult(0), mCachedResultValid(false)
{
}
QueryVk::~QueryVk() = default;
gl::Error QueryVk::onDestroy(const gl::Context *context)
{
ContextVk *contextVk = vk::GetImpl(context);
contextVk->getQueryPool(getType())->freeQuery(contextVk, &mQueryHelper);
return gl::NoError();
}
gl::Error QueryVk::begin(const gl::Context *context)
{
ContextVk *contextVk = vk::GetImpl(context);
ANGLE_TRY(contextVk->getQueryPool(getType())->allocateQuery(contextVk, &mQueryHelper));
mCachedResultValid = false;
mQueryHelper.beginQuery(contextVk, mQueryHelper.getQueryPool(), mQueryHelper.getQuery());
return gl::NoError();
}
gl::Error QueryVk::end(const gl::Context *context)
{
ContextVk *contextVk = vk::GetImpl(context);
mQueryHelper.endQuery(contextVk, mQueryHelper.getQueryPool(), mQueryHelper.getQuery());
return gl::NoError();
}
gl::Error QueryVk::queryCounter(const gl::Context *context)
{
UNIMPLEMENTED();
return gl::InternalError();
}
angle::Result QueryVk::getResult(const gl::Context *context, bool wait)
{
if (mCachedResultValid)
{
return angle::Result::Continue();
}
ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer();
// glGetQueryObject* requires an implicit flush of the command buffers to guarantee execution in
// finite time.
if (mQueryHelper.hasPendingWork(renderer))
{
ANGLE_TRY_HANDLE(context, renderer->flush(contextVk));
ASSERT(!mQueryHelper.hasPendingWork(renderer));
}
// If the command buffer this query is being written to is still in flight, its reset command
// may not have been performed by the GPU yet. To avoid a race condition in this case, wait
// for the batch to finish first before querying (or return not-ready if not waiting).
ANGLE_TRY(renderer->checkCompletedCommands(contextVk));
if (mQueryHelper.isResourceInUse(renderer))
{
if (!wait)
{
return angle::Result::Continue();
}
ANGLE_TRY(renderer->finishToSerial(contextVk, mQueryHelper.getStoredQueueSerial()));
}
VkQueryResultFlags flags = (wait ? VK_QUERY_RESULT_WAIT_BIT : 0) | VK_QUERY_RESULT_64_BIT;
angle::Result result = mQueryHelper.getQueryPool()->getResults(
contextVk, mQueryHelper.getQuery(), 1, sizeof(mCachedResult), &mCachedResult,
sizeof(mCachedResult), flags);
ANGLE_TRY(result);
// If the results are not ready, do nothing. mCachedResultValid remains false.
if (result == angle::Result::Incomplete())
{
// If VK_QUERY_RESULT_WAIT_BIT was given, Incomplete() cannot have been returned.
ASSERT(!wait);
return angle::Result::Continue();
}
// Fix up the results to what OpenGL expects.
switch (getType())
{
case gl::QueryType::AnySamples:
case gl::QueryType::AnySamplesConservative:
// OpenGL query result in these cases is binary
mCachedResult = !!mCachedResult;
break;
default:
UNREACHABLE();
break;
}
mCachedResultValid = true;
return angle::Result::Continue();
}
gl::Error QueryVk::getResult(const gl::Context *context, GLint *params)
{
ANGLE_TRY(getResult(context, true));
*params = static_cast<GLint>(mCachedResult);
return gl::NoError();
}
gl::Error QueryVk::getResult(const gl::Context *context, GLuint *params)
{
ANGLE_TRY(getResult(context, true));
*params = static_cast<GLuint>(mCachedResult);
return gl::NoError();
}
gl::Error QueryVk::getResult(const gl::Context *context, GLint64 *params)
{
ANGLE_TRY(getResult(context, true));
*params = static_cast<GLint64>(mCachedResult);
return gl::NoError();
}
gl::Error QueryVk::getResult(const gl::Context *context, GLuint64 *params)
{
ANGLE_TRY(getResult(context, true));
*params = mCachedResult;
return gl::NoError();
}
gl::Error QueryVk::isResultAvailable(const gl::Context *context, bool *available)
{
ANGLE_TRY(getResult(context, false));
*available = mCachedResultValid;
return gl::NoError();
}
} // namespace rx