Commit 6328caf3 by Charlie Lao Committed by Commit Bot

Vulkan: Avoid renderpass break for occlusion query

This ensures beginQuery and endQuery only get inserted into renderpasses and will not close renderpass because of query call Bug: angleproject:4381 Change-Id: I690f096b9e8e4b7ea9a67045d1be0fd7a319c98c Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2119246Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com> Commit-Queue: Charlie Lao <cclao@google.com>
parent 4b94d7bb
...@@ -39,6 +39,15 @@ class QueryImpl : angle::NonCopyable ...@@ -39,6 +39,15 @@ class QueryImpl : angle::NonCopyable
gl::QueryType getType() const { return mType; } gl::QueryType getType() const { return mType; }
// Convenient functions
bool isOcclusionQuery() const { return isAnySamplesQuery() || isAnySamplesConservativeQuery(); }
bool isAnySamplesQuery() const { return getType() == gl::QueryType::AnySamples; }
bool isAnySamplesConservativeQuery() const
{
return getType() == gl::QueryType::AnySamplesConservative;
}
private: private:
gl::QueryType mType; gl::QueryType mType;
}; };
......
...@@ -69,6 +69,7 @@ class Serial final ...@@ -69,6 +69,7 @@ class Serial final
// Useful for serialization. // Useful for serialization.
constexpr uint64_t getValue() const { return mValue; } constexpr uint64_t getValue() const { return mValue; }
constexpr bool valid() const { return mValue != kInvalid; }
private: private:
template <typename T> template <typename T>
......
...@@ -599,6 +599,8 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk ...@@ -599,6 +599,8 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
mDrawFramebuffer(nullptr), mDrawFramebuffer(nullptr),
mProgram(nullptr), mProgram(nullptr),
mExecutable(nullptr), mExecutable(nullptr),
mActiveQueryAnySamples(nullptr),
mActiveQueryAnySamplesConservative(nullptr),
mLastIndexBufferOffset(0), mLastIndexBufferOffset(0),
mCurrentDrawElementsType(gl::DrawElementsType::InvalidEnum), mCurrentDrawElementsType(gl::DrawElementsType::InvalidEnum),
mXfbBaseVertex(0), mXfbBaseVertex(0),
...@@ -899,11 +901,8 @@ angle::Result ContextVk::setupDraw(const gl::Context *context, ...@@ -899,11 +901,8 @@ angle::Result ContextVk::setupDraw(const gl::Context *context,
// TODO(jmadill): Use dirty bit. http://anglebug.com/3014 // TODO(jmadill): Use dirty bit. http://anglebug.com/3014
if (!mRenderPassCommandBuffer) if (!mRenderPassCommandBuffer)
{ {
mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits;
gl::Rectangle scissoredRenderArea = mDrawFramebuffer->getScissoredRenderArea(this); gl::Rectangle scissoredRenderArea = mDrawFramebuffer->getScissoredRenderArea(this);
ANGLE_TRY(mDrawFramebuffer->startNewRenderPass(this, scissoredRenderArea, ANGLE_TRY(startRenderPass(scissoredRenderArea));
&mRenderPassCommandBuffer));
} }
// We keep a local copy of the command buffer. It's possible that some state changes could // We keep a local copy of the command buffer. It's possible that some state changes could
...@@ -1629,7 +1628,7 @@ angle::Result ContextVk::synchronizeCpuGpuTime() ...@@ -1629,7 +1628,7 @@ angle::Result ContextVk::synchronizeCpuGpuTime()
commandBuffer.waitEvents(1, cpuReady.get().ptr(), VK_PIPELINE_STAGE_HOST_BIT, commandBuffer.waitEvents(1, cpuReady.get().ptr(), VK_PIPELINE_STAGE_HOST_BIT,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, nullptr, 0, nullptr, 0, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, nullptr, 0, nullptr, 0,
nullptr); nullptr);
timestampQuery.writeTimestamp(&commandBuffer); timestampQuery.writeTimestamp(this, &commandBuffer);
commandBuffer.setEvent(gpuDone.get().getHandle(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT); commandBuffer.setEvent(gpuDone.get().getHandle(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT);
ANGLE_VK_TRY(this, commandBuffer.end()); ANGLE_VK_TRY(this, commandBuffer.end());
...@@ -1719,7 +1718,7 @@ angle::Result ContextVk::traceGpuEventImpl(vk::PrimaryCommandBuffer *commandBuff ...@@ -1719,7 +1718,7 @@ angle::Result ContextVk::traceGpuEventImpl(vk::PrimaryCommandBuffer *commandBuff
gpuEvent.phase = phase; gpuEvent.phase = phase;
ANGLE_TRY(mGpuEventQueryPool.allocateQuery(this, &gpuEvent.queryHelper)); ANGLE_TRY(mGpuEventQueryPool.allocateQuery(this, &gpuEvent.queryHelper));
gpuEvent.queryHelper.writeTimestamp(commandBuffer); gpuEvent.queryHelper.writeTimestamp(this, commandBuffer);
mInFlightGpuEventQueries.push_back(std::move(gpuEvent)); mInFlightGpuEventQueries.push_back(std::move(gpuEvent));
return angle::Result::Continue; return angle::Result::Continue;
...@@ -2220,8 +2219,7 @@ angle::Result ContextVk::clearWithRenderPassOp( ...@@ -2220,8 +2219,7 @@ angle::Result ContextVk::clearWithRenderPassOp(
(mRenderPassCommands.started() && !mRenderPassCommands.empty()) || (mRenderPassCommands.started() && !mRenderPassCommands.empty()) ||
mRenderPassCommands.getRenderArea() != clearArea) mRenderPassCommands.getRenderArea() != clearArea)
{ {
mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits; ANGLE_TRY(startRenderPass(clearArea));
ANGLE_TRY(mDrawFramebuffer->startNewRenderPass(this, clearArea, &mRenderPassCommandBuffer));
} }
else else
{ {
...@@ -3861,7 +3859,7 @@ angle::Result ContextVk::getTimestamp(uint64_t *timestampOut) ...@@ -3861,7 +3859,7 @@ angle::Result ContextVk::getTimestamp(uint64_t *timestampOut)
beginInfo.pInheritanceInfo = nullptr; beginInfo.pInheritanceInfo = nullptr;
ANGLE_VK_TRY(this, commandBuffer.begin(beginInfo)); ANGLE_VK_TRY(this, commandBuffer.begin(beginInfo));
timestampQuery.writeTimestamp(&commandBuffer); timestampQuery.writeTimestamp(this, &commandBuffer);
ANGLE_VK_TRY(this, commandBuffer.end()); ANGLE_VK_TRY(this, commandBuffer.end());
// Create fence for the submission // Create fence for the submission
...@@ -4072,14 +4070,45 @@ angle::Result ContextVk::flushAndBeginRenderPass( ...@@ -4072,14 +4070,45 @@ angle::Result ContextVk::flushAndBeginRenderPass(
return angle::Result::Continue; return angle::Result::Continue;
} }
ANGLE_INLINE angle::Result ContextVk::startRenderPass(gl::Rectangle renderArea)
{
mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits;
ANGLE_TRY(mDrawFramebuffer->startNewRenderPass(this, renderArea, &mRenderPassCommandBuffer));
if (mActiveQueryAnySamples)
{
mActiveQueryAnySamples->getQueryHelper()->beginOcclusionQuery(this, &mPrimaryCommands,
mRenderPassCommandBuffer);
}
if (mActiveQueryAnySamplesConservative)
{
mActiveQueryAnySamplesConservative->getQueryHelper()->beginOcclusionQuery(
this, &mPrimaryCommands, mRenderPassCommandBuffer);
}
return angle::Result::Continue;
}
angle::Result ContextVk::endRenderPass() angle::Result ContextVk::endRenderPass()
{ {
onRenderPassFinished();
if (mRenderPassCommands.empty()) if (mRenderPassCommands.empty())
{ {
onRenderPassFinished();
return angle::Result::Continue; return angle::Result::Continue;
} }
if (mActiveQueryAnySamples)
{
mActiveQueryAnySamples->getQueryHelper()->endOcclusionQuery(this, mRenderPassCommandBuffer);
ANGLE_TRY(mActiveQueryAnySamples->stashQueryHelper(this));
}
if (mActiveQueryAnySamplesConservative)
{
mActiveQueryAnySamplesConservative->getQueryHelper()->endOcclusionQuery(
this, mRenderPassCommandBuffer);
ANGLE_TRY(mActiveQueryAnySamplesConservative->stashQueryHelper(this));
}
onRenderPassFinished();
if (mGpuEventsEnabled) if (mGpuEventsEnabled)
{ {
mRenderPassCounter++; mRenderPassCounter++;
...@@ -4193,6 +4222,53 @@ void ContextVk::flushOutsideRenderPassCommands() ...@@ -4193,6 +4222,53 @@ void ContextVk::flushOutsideRenderPassCommands()
} }
} }
void ContextVk::beginOcclusionQuery(QueryVk *queryVk)
{
// To avoid complexity, we always start and end occlusion query inside renderpass. if renderpass
// not yet started, we just remember it and defer the start call.
if (mRenderPassCommands.started())
{
queryVk->getQueryHelper()->beginOcclusionQuery(this, &mPrimaryCommands,
mRenderPassCommandBuffer);
}
if (queryVk->isAnySamplesQuery())
{
ASSERT(mActiveQueryAnySamples == nullptr);
mActiveQueryAnySamples = queryVk;
}
else if (queryVk->isAnySamplesConservativeQuery())
{
ASSERT(mActiveQueryAnySamplesConservative == nullptr);
mActiveQueryAnySamplesConservative = queryVk;
}
else
{
UNREACHABLE();
}
}
void ContextVk::endOcclusionQuery(QueryVk *queryVk)
{
if (mRenderPassCommands.started())
{
queryVk->getQueryHelper()->endOcclusionQuery(this, mRenderPassCommandBuffer);
}
if (queryVk->isAnySamplesQuery())
{
ASSERT(mActiveQueryAnySamples == queryVk);
mActiveQueryAnySamples = nullptr;
}
else if (queryVk->isAnySamplesConservativeQuery())
{
ASSERT(mActiveQueryAnySamplesConservative == queryVk);
mActiveQueryAnySamplesConservative = nullptr;
}
else
{
UNREACHABLE();
}
}
CommandBufferHelper::CommandBufferHelper() CommandBufferHelper::CommandBufferHelper()
: mImageBarrierSrcStageMask(0), : mImageBarrierSrcStageMask(0),
mImageBarrierDstStageMask(0), mImageBarrierDstStageMask(0),
......
...@@ -648,6 +648,7 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -648,6 +648,7 @@ class ContextVk : public ContextImpl, public vk::Context
} }
egl::ContextPriority getContextPriority() const override { return mContextPriority; } egl::ContextPriority getContextPriority() const override { return mContextPriority; }
angle::Result startRenderPass(gl::Rectangle renderArea);
angle::Result endRenderPass(); angle::Result endRenderPass();
angle::Result syncExternalMemory(); angle::Result syncExternalMemory();
...@@ -663,6 +664,10 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -663,6 +664,10 @@ class ContextVk : public ContextImpl, public vk::Context
ProgramVk *getShaderProgram(const gl::State &glState, gl::ShaderType shaderType) const; ProgramVk *getShaderProgram(const gl::State &glState, gl::ShaderType shaderType) const;
// occlusion query
void beginOcclusionQuery(QueryVk *queryVk);
void endOcclusionQuery(QueryVk *queryVk);
private: private:
// Dirty bits. // Dirty bits.
enum DirtyBitType : size_t enum DirtyBitType : size_t
...@@ -958,6 +963,10 @@ class ContextVk : public ContextImpl, public vk::Context ...@@ -958,6 +963,10 @@ class ContextVk : public ContextImpl, public vk::Context
ProgramVk *mProgram; ProgramVk *mProgram;
ProgramExecutableVk *mExecutable; ProgramExecutableVk *mExecutable;
// occlusion query
QueryVk *mActiveQueryAnySamples;
QueryVk *mActiveQueryAnySamplesConservative;
// Graph resource used to record dispatch commands and hold resource dependencies. // Graph resource used to record dispatch commands and hold resource dependencies.
vk::DispatchHelper mDispatcher; vk::DispatchHelper mDispatcher;
......
...@@ -39,6 +39,29 @@ void QueryVk::onDestroy(const gl::Context *context) ...@@ -39,6 +39,29 @@ void QueryVk::onDestroy(const gl::Context *context)
} }
} }
angle::Result QueryVk::stashQueryHelper(ContextVk *contextVk)
{
ASSERT(isOcclusionQuery());
mStashedQueryHelpers.emplace_back(mQueryHelper);
mQueryHelper.deinit();
ANGLE_TRY(contextVk->getQueryPool(getType())->allocateQuery(contextVk, &mQueryHelper));
return angle::Result::Continue;
}
angle::Result QueryVk::retrieveStashedQueryResult(ContextVk *contextVk, uint64_t *result)
{
uint64_t total = 0;
for (vk::QueryHelper &query : mStashedQueryHelpers)
{
uint64_t v;
ANGLE_TRY(query.getUint64Result(contextVk, &v));
total += v;
}
mStashedQueryHelpers.clear();
*result = total;
return angle::Result::Continue;
}
angle::Result QueryVk::begin(const gl::Context *context) angle::Result QueryVk::begin(const gl::Context *context)
{ {
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
...@@ -58,9 +81,25 @@ angle::Result QueryVk::begin(const gl::Context *context) ...@@ -58,9 +81,25 @@ angle::Result QueryVk::begin(const gl::Context *context)
ANGLE_TRY(contextVk->getQueryPool(getType())->allocateQuery(contextVk, &mQueryHelper)); ANGLE_TRY(contextVk->getQueryPool(getType())->allocateQuery(contextVk, &mQueryHelper));
} }
// Note: TimeElapsed is implemented by using two Timestamp queries and taking the diff. if (isOcclusionQuery())
if (getType() == gl::QueryType::TimeElapsed)
{ {
// For pathological usage case where begin/end is called back to back without flush and get
// result, we have to force flush so that the same mQueryHelper will not encoded in the same
// renderpass twice without resetting it.
if (mQueryHelper.hasPendingWork(contextVk))
{
ANGLE_TRY(contextVk->flushImpl(nullptr));
// As soon as beginQuery is called, previous query's result will not retrievable by API.
// We must clear it so that it will not count against current beginQuery call.
mStashedQueryHelpers.clear();
mQueryHelper.deinit();
ANGLE_TRY(contextVk->getQueryPool(getType())->allocateQuery(contextVk, &mQueryHelper));
}
contextVk->beginOcclusionQuery(this);
}
else if (getType() == gl::QueryType::TimeElapsed)
{
// Note: TimeElapsed is implemented by using two Timestamp queries and taking the diff.
if (!mQueryHelperTimeElapsedBegin.valid()) if (!mQueryHelperTimeElapsedBegin.valid())
{ {
ANGLE_TRY(contextVk->getQueryPool(getType())->allocateQuery( ANGLE_TRY(contextVk->getQueryPool(getType())->allocateQuery(
...@@ -96,6 +135,10 @@ angle::Result QueryVk::end(const gl::Context *context) ...@@ -96,6 +135,10 @@ angle::Result QueryVk::end(const gl::Context *context)
mCachedResultValid = true; mCachedResultValid = true;
// We could consider using VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT. // We could consider using VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT.
} }
else if (isOcclusionQuery())
{
contextVk->endOcclusionQuery(this);
}
else if (getType() == gl::QueryType::TimeElapsed) else if (getType() == gl::QueryType::TimeElapsed)
{ {
ANGLE_TRY(mQueryHelper.flushAndWriteTimestamp(contextVk)); ANGLE_TRY(mQueryHelper.flushAndWriteTimestamp(contextVk));
...@@ -110,6 +153,7 @@ angle::Result QueryVk::end(const gl::Context *context) ...@@ -110,6 +153,7 @@ angle::Result QueryVk::end(const gl::Context *context)
angle::Result QueryVk::queryCounter(const gl::Context *context) angle::Result QueryVk::queryCounter(const gl::Context *context)
{ {
ASSERT(getType() == gl::QueryType::Timestamp);
ContextVk *contextVk = vk::GetImpl(context); ContextVk *contextVk = vk::GetImpl(context);
mCachedResultValid = false; mCachedResultValid = false;
...@@ -119,8 +163,6 @@ angle::Result QueryVk::queryCounter(const gl::Context *context) ...@@ -119,8 +163,6 @@ angle::Result QueryVk::queryCounter(const gl::Context *context)
ANGLE_TRY(contextVk->getQueryPool(getType())->allocateQuery(contextVk, &mQueryHelper)); ANGLE_TRY(contextVk->getQueryPool(getType())->allocateQuery(contextVk, &mQueryHelper));
} }
ASSERT(getType() == gl::QueryType::Timestamp);
return mQueryHelper.flushAndWriteTimestamp(contextVk); return mQueryHelper.flushAndWriteTimestamp(contextVk);
} }
...@@ -162,6 +204,9 @@ angle::Result QueryVk::getResult(const gl::Context *context, bool wait) ...@@ -162,6 +204,9 @@ angle::Result QueryVk::getResult(const gl::Context *context, bool wait)
if (wait) if (wait)
{ {
ANGLE_TRY(mQueryHelper.getUint64Result(contextVk, &mCachedResult)); ANGLE_TRY(mQueryHelper.getUint64Result(contextVk, &mCachedResult));
uint64_t v;
ANGLE_TRY(retrieveStashedQueryResult(contextVk, &v));
mCachedResult += v;
} }
else else
{ {
...@@ -172,6 +217,9 @@ angle::Result QueryVk::getResult(const gl::Context *context, bool wait) ...@@ -172,6 +217,9 @@ angle::Result QueryVk::getResult(const gl::Context *context, bool wait)
// If the results are not ready, do nothing. mCachedResultValid remains false. // If the results are not ready, do nothing. mCachedResultValid remains false.
return angle::Result::Continue; return angle::Result::Continue;
} }
uint64_t v;
ANGLE_TRY(retrieveStashedQueryResult(contextVk, &v));
mCachedResult += v;
} }
double timestampPeriod = renderer->getPhysicalDeviceProperties().limits.timestampPeriod; double timestampPeriod = renderer->getPhysicalDeviceProperties().limits.timestampPeriod;
......
...@@ -35,12 +35,17 @@ class QueryVk : public QueryImpl ...@@ -35,12 +35,17 @@ class QueryVk : public QueryImpl
angle::Result isResultAvailable(const gl::Context *context, bool *available) override; angle::Result isResultAvailable(const gl::Context *context, bool *available) override;
void onTransformFeedbackEnd(const gl::Context *context); void onTransformFeedbackEnd(const gl::Context *context);
vk::QueryHelper *getQueryHelper() { return &mQueryHelper; }
angle::Result stashQueryHelper(ContextVk *contextVk);
angle::Result retrieveStashedQueryResult(ContextVk *contextVk, uint64_t *result);
private: private:
angle::Result getResult(const gl::Context *context, bool wait); angle::Result getResult(const gl::Context *context, bool wait);
// Used for AnySamples, AnySamplesConservative, Timestamp and TimeElapsed (end). // Used for AnySamples, AnySamplesConservative, Timestamp and TimeElapsed (end).
vk::QueryHelper mQueryHelper; vk::QueryHelper mQueryHelper;
// Used for occlusion query that we may end up with multiple outstanding query helper objects.
std::vector<vk::QueryHelper> mStashedQueryHelpers;
// An additional query used for TimeElapsed (begin), as it is implemented using Timestamp. // An additional query used for TimeElapsed (begin), as it is implemented using Timestamp.
vk::QueryHelper mQueryHelperTimeElapsedBegin; vk::QueryHelper mQueryHelperTimeElapsedBegin;
// Used with TransformFeedbackPrimitivesWritten when transform feedback is emulated. // Used with TransformFeedbackPrimitivesWritten when transform feedback is emulated.
......
...@@ -1006,6 +1006,7 @@ void QueryHelper::deinit() ...@@ -1006,6 +1006,7 @@ void QueryHelper::deinit()
mDynamicQueryPool = nullptr; mDynamicQueryPool = nullptr;
mQueryPoolIndex = 0; mQueryPoolIndex = 0;
mQuery = 0; mQuery = 0;
mMostRecentSerial = Serial();
} }
angle::Result QueryHelper::beginQuery(ContextVk *contextVk) angle::Result QueryHelper::beginQuery(ContextVk *contextVk)
...@@ -1028,27 +1029,44 @@ angle::Result QueryHelper::endQuery(ContextVk *contextVk) ...@@ -1028,27 +1029,44 @@ angle::Result QueryHelper::endQuery(ContextVk *contextVk)
return angle::Result::Continue; return angle::Result::Continue;
} }
void QueryHelper::beginOcclusionQuery(ContextVk *contextVk,
PrimaryCommandBuffer *primaryCommands,
CommandBuffer *renderPassCommandBuffer)
{
const QueryPool &queryPool = getQueryPool();
// reset has to be encoded in primary command buffer per spec
primaryCommands->resetQueryPool(queryPool, mQuery, 1);
renderPassCommandBuffer->beginQuery(queryPool.getHandle(), mQuery, 0);
mMostRecentSerial = contextVk->getCurrentQueueSerial();
}
void QueryHelper::endOcclusionQuery(ContextVk *contextVk, CommandBuffer *renderPassCommandBuffer)
{
renderPassCommandBuffer->endQuery(getQueryPool().getHandle(), mQuery);
mMostRecentSerial = contextVk->getCurrentQueueSerial();
}
angle::Result QueryHelper::flushAndWriteTimestamp(ContextVk *contextVk) angle::Result QueryHelper::flushAndWriteTimestamp(ContextVk *contextVk)
{ {
vk::PrimaryCommandBuffer *primary; vk::PrimaryCommandBuffer *primary;
ANGLE_TRY(contextVk->flushAndGetPrimaryCommandBuffer(&primary)); ANGLE_TRY(contextVk->flushAndGetPrimaryCommandBuffer(&primary));
writeTimestamp(primary); writeTimestamp(contextVk, primary);
mMostRecentSerial = contextVk->getCurrentQueueSerial();
return angle::Result::Continue; return angle::Result::Continue;
} }
void QueryHelper::writeTimestamp(vk::PrimaryCommandBuffer *primary) void QueryHelper::writeTimestamp(ContextVk *contextVk, PrimaryCommandBuffer *primary)
{ {
const QueryPool &queryPool = getQueryPool(); const QueryPool &queryPool = getQueryPool();
primary->resetQueryPool(queryPool, mQuery, 1); primary->resetQueryPool(queryPool, mQuery, 1);
primary->writeTimestamp(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, queryPool, mQuery); primary->writeTimestamp(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, queryPool, mQuery);
mMostRecentSerial = contextVk->getCurrentQueueSerial();
} }
bool QueryHelper::hasPendingWork(ContextVk *contextVk) bool QueryHelper::hasPendingWork(ContextVk *contextVk)
{ {
// If the renderer has a queue serial higher than the stored one, the command buffers that // If the renderer has a queue serial higher than the stored one, the command buffers that
// recorded this query have already been submitted, so there is no pending work. // recorded this query have already been submitted, so there is no pending work.
return mMostRecentSerial == contextVk->getCurrentQueueSerial(); return mMostRecentSerial.valid() && (mMostRecentSerial == contextVk->getCurrentQueueSerial());
} }
angle::Result QueryHelper::getUint64ResultNonBlocking(ContextVk *contextVk, angle::Result QueryHelper::getUint64ResultNonBlocking(ContextVk *contextVk,
...@@ -1056,10 +1074,22 @@ angle::Result QueryHelper::getUint64ResultNonBlocking(ContextVk *contextVk, ...@@ -1056,10 +1074,22 @@ angle::Result QueryHelper::getUint64ResultNonBlocking(ContextVk *contextVk,
bool *availableOut) bool *availableOut)
{ {
ASSERT(valid()); ASSERT(valid());
VkDevice device = contextVk->getDevice(); VkResult result;
constexpr VkQueryResultFlags kFlags = VK_QUERY_RESULT_64_BIT;
VkResult result = getQueryPool().getResults(device, mQuery, 1, sizeof(uint64_t), resultOut, // Ensure that we only wait if we have inserted a query in command buffer. Otherwise you will
sizeof(uint64_t), kFlags); // wait forever and trigger GPU timeout.
if (mMostRecentSerial.valid())
{
VkDevice device = contextVk->getDevice();
constexpr VkQueryResultFlags kFlags = VK_QUERY_RESULT_64_BIT;
result = getQueryPool().getResults(device, mQuery, 1, sizeof(uint64_t), resultOut,
sizeof(uint64_t), kFlags);
}
else
{
result = VK_SUCCESS;
*resultOut = 0;
}
if (result == VK_NOT_READY) if (result == VK_NOT_READY)
{ {
...@@ -1077,10 +1107,17 @@ angle::Result QueryHelper::getUint64ResultNonBlocking(ContextVk *contextVk, ...@@ -1077,10 +1107,17 @@ angle::Result QueryHelper::getUint64ResultNonBlocking(ContextVk *contextVk,
angle::Result QueryHelper::getUint64Result(ContextVk *contextVk, uint64_t *resultOut) angle::Result QueryHelper::getUint64Result(ContextVk *contextVk, uint64_t *resultOut)
{ {
ASSERT(valid()); ASSERT(valid());
VkDevice device = contextVk->getDevice(); if (mMostRecentSerial.valid())
constexpr VkQueryResultFlags kFlags = VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT; {
ANGLE_VK_TRY(contextVk, getQueryPool().getResults(device, mQuery, 1, sizeof(uint64_t), VkDevice device = contextVk->getDevice();
resultOut, sizeof(uint64_t), kFlags)); constexpr VkQueryResultFlags kFlags = VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT;
ANGLE_VK_TRY(contextVk, getQueryPool().getResults(device, mQuery, 1, sizeof(uint64_t),
resultOut, sizeof(uint64_t), kFlags));
}
else
{
*resultOut = 0;
}
return angle::Result::Continue; return angle::Result::Continue;
} }
......
...@@ -315,8 +315,14 @@ class QueryHelper final ...@@ -315,8 +315,14 @@ class QueryHelper final
angle::Result beginQuery(ContextVk *contextVk); angle::Result beginQuery(ContextVk *contextVk);
angle::Result endQuery(ContextVk *contextVk); angle::Result endQuery(ContextVk *contextVk);
// for occlusion query
void beginOcclusionQuery(ContextVk *contextVk,
PrimaryCommandBuffer *primaryCommands,
CommandBuffer *renderPassCommandBuffer);
void endOcclusionQuery(ContextVk *contextVk, CommandBuffer *renderPassCommandBuffer);
angle::Result flushAndWriteTimestamp(ContextVk *contextVk); angle::Result flushAndWriteTimestamp(ContextVk *contextVk);
void writeTimestamp(vk::PrimaryCommandBuffer *primary); void writeTimestamp(ContextVk *contextVk, PrimaryCommandBuffer *primary);
Serial getStoredQueueSerial() { return mMostRecentSerial; } Serial getStoredQueueSerial() { return mMostRecentSerial; }
bool hasPendingWork(ContextVk *contextVk); bool hasPendingWork(ContextVk *contextVk);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment