Commit 4375d6c7 by Shahbaz Youssefi Committed by Angle LUCI CQ

Vulkan: Support multiview queries

When using queries with multiview, Vulkan specifies that N queries are actually produced (N being the number of views) which must be summed by the application. Bug: angleproject:6048 Change-Id: I5ea615536f1a357806b7ea8093280b9122f1d66a Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2971562 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCharlie Lao <cclao@google.com>
parent 977a28f3
......@@ -2270,7 +2270,7 @@ angle::Result ContextVk::synchronizeCpuGpuTime()
// Create a query used to receive the GPU timestamp
vk::QueryHelper timestampQuery;
ANGLE_TRY(mGpuEventQueryPool.allocateQuery(this, &timestampQuery));
ANGLE_TRY(mGpuEventQueryPool.allocateQuery(this, &timestampQuery, 1));
// Create the three events
VkEventCreateInfo eventCreateInfo = {};
......@@ -2402,7 +2402,7 @@ angle::Result ContextVk::traceGpuEventImpl(vk::CommandBuffer *commandBuffer,
GpuEventQuery gpuEvent;
gpuEvent.name = name;
gpuEvent.phase = phase;
ANGLE_TRY(mGpuEventQueryPool.allocateQuery(this, &gpuEvent.queryHelper));
ANGLE_TRY(mGpuEventQueryPool.allocateQuery(this, &gpuEvent.queryHelper, 1));
gpuEvent.queryHelper.writeTimestamp(this, commandBuffer);
......@@ -5374,7 +5374,7 @@ angle::Result ContextVk::getTimestamp(uint64_t *timestampOut)
vk::DeviceScoped<vk::DynamicQueryPool> timestampQueryPool(device);
vk::QueryHelper timestampQuery;
ANGLE_TRY(timestampQueryPool.get().init(this, VK_QUERY_TYPE_TIMESTAMP, 1));
ANGLE_TRY(timestampQueryPool.get().allocateQuery(this, &timestampQuery));
ANGLE_TRY(timestampQueryPool.get().allocateQuery(this, &timestampQuery, 1));
vk::ResourceUseList scratchResourceUseList;
......@@ -5598,6 +5598,12 @@ uint32_t ContextVk::getCurrentSubpassIndex() const
return mGraphicsPipelineDesc->getSubpass();
}
uint32_t ContextVk::getCurrentViewCount() const
{
ASSERT(mDrawFramebuffer);
return mDrawFramebuffer->getRenderPassDesc().viewCount();
}
angle::Result ContextVk::flushCommandsAndEndRenderPassImpl()
{
// Ensure we flush the RenderPass *after* the prior commands.
......
......@@ -558,6 +558,7 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
void restoreFinishedRenderPass(vk::Framebuffer *framebuffer);
uint32_t getCurrentSubpassIndex() const;
uint32_t getCurrentViewCount() const;
egl::ContextPriority getContextPriority() const override { return mContextPriority; }
angle::Result startRenderPass(gl::Rectangle renderArea,
......
......@@ -117,7 +117,18 @@ angle::Result QueryVk::allocateQuery(ContextVk *contextVk)
ASSERT(!mQueryHelper.isReferenced());
mQueryHelper.setUnreferenced(new vk::RefCounted<vk::QueryHelper>);
return contextVk->getQueryPool(mType)->allocateQuery(contextVk, &mQueryHelper.get());
// When used with multiview, render pass queries write as many queries as the number of views.
// Render pass queries are always allocated at the beginning of the render pass, so the number
// of views is known at this time.
uint32_t queryCount = 1;
if (IsRenderPassQuery(contextVk, mType))
{
ASSERT(contextVk->hasStartedRenderPass());
queryCount = std::max(contextVk->getCurrentViewCount(), 1u);
}
return contextVk->getQueryPool(mType)->allocateQuery(contextVk, &mQueryHelper.get(),
queryCount);
}
void QueryVk::assignSharedQuery(QueryVk *shareQuery)
......@@ -318,8 +329,10 @@ angle::Result QueryVk::begin(const gl::Context *context)
// Note: TimeElapsed is implemented by using two Timestamp queries and taking the diff.
if (!mQueryHelperTimeElapsedBegin.valid())
{
// Note that timestamp queries are not allowed with multiview, so query count is
// always 1.
ANGLE_TRY(contextVk->getQueryPool(mType)->allocateQuery(
contextVk, &mQueryHelperTimeElapsedBegin));
contextVk, &mQueryHelperTimeElapsedBegin, 1));
}
ANGLE_TRY(mQueryHelperTimeElapsedBegin.flushAndWriteTimestamp(contextVk));
......
......@@ -2680,18 +2680,22 @@ void DynamicQueryPool::destroy(VkDevice device)
destroyEntryPool();
}
angle::Result DynamicQueryPool::allocateQuery(ContextVk *contextVk, QueryHelper *queryOut)
angle::Result DynamicQueryPool::allocateQuery(ContextVk *contextVk,
QueryHelper *queryOut,
uint32_t queryCount)
{
ASSERT(!queryOut->valid());
if (mCurrentFreeEntry >= mPoolSize)
if (mCurrentFreeEntry + queryCount > mPoolSize)
{
// No more queries left in this pool, create another one.
ANGLE_TRY(allocateNewPool(contextVk));
}
uint32_t queryIndex = mCurrentFreeEntry++;
queryOut->init(this, mCurrentPool, queryIndex);
uint32_t queryIndex = mCurrentFreeEntry;
mCurrentFreeEntry += queryCount;
queryOut->init(this, mCurrentPool, queryIndex, queryCount);
return angle::Result::Continue;
}
......@@ -2735,8 +2739,27 @@ angle::Result DynamicQueryPool::allocateNewPool(ContextVk *contextVk)
return allocateNewEntryPool(contextVk, std::move(queryPool));
}
// QueryResult implementation
void QueryResult::setResults(uint64_t *results, uint32_t queryCount)
{
ASSERT(mResults[0] == 0 && mResults[1] == 0);
// Accumulate the query results. For multiview, where multiple query indices are used to return
// the results, it's undefined how the results are distributed between indices, but the sum is
// guaranteed to be the desired result.
for (uint32_t query = 0; query < queryCount; ++query)
{
for (uint32_t perQueryIndex = 0; perQueryIndex < mIntsPerResult; ++perQueryIndex)
{
mResults[perQueryIndex] += results[query * mIntsPerResult + perQueryIndex];
}
}
}
// QueryHelper implementation
QueryHelper::QueryHelper() : mDynamicQueryPool(nullptr), mQueryPoolIndex(0), mQuery(0) {}
QueryHelper::QueryHelper()
: mDynamicQueryPool(nullptr), mQueryPoolIndex(0), mQuery(0), mQueryCount(0)
{}
QueryHelper::~QueryHelper() {}
......@@ -2745,11 +2768,13 @@ QueryHelper::QueryHelper(QueryHelper &&rhs)
: Resource(std::move(rhs)),
mDynamicQueryPool(rhs.mDynamicQueryPool),
mQueryPoolIndex(rhs.mQueryPoolIndex),
mQuery(rhs.mQuery)
mQuery(rhs.mQuery),
mQueryCount(rhs.mQueryCount)
{
rhs.mDynamicQueryPool = nullptr;
rhs.mQueryPoolIndex = 0;
rhs.mQuery = 0;
rhs.mQueryCount = 0;
}
QueryHelper &QueryHelper::operator=(QueryHelper &&rhs)
......@@ -2757,16 +2782,21 @@ QueryHelper &QueryHelper::operator=(QueryHelper &&rhs)
std::swap(mDynamicQueryPool, rhs.mDynamicQueryPool);
std::swap(mQueryPoolIndex, rhs.mQueryPoolIndex);
std::swap(mQuery, rhs.mQuery);
std::swap(mQueryCount, rhs.mQueryCount);
return *this;
}
void QueryHelper::init(const DynamicQueryPool *dynamicQueryPool,
const size_t queryPoolIndex,
uint32_t query)
uint32_t query,
uint32_t queryCount)
{
mDynamicQueryPool = dynamicQueryPool;
mQueryPoolIndex = queryPoolIndex;
mQuery = query;
mQueryCount = queryCount;
ASSERT(mQueryCount <= gl::IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS);
}
void QueryHelper::deinit()
......@@ -2774,6 +2804,7 @@ void QueryHelper::deinit()
mDynamicQueryPool = nullptr;
mQueryPoolIndex = 0;
mQuery = 0;
mQueryCount = 0;
mUse.release();
mUse.init();
}
......@@ -2783,7 +2814,7 @@ void QueryHelper::beginQueryImpl(ContextVk *contextVk,
CommandBuffer *commandBuffer)
{
const QueryPool &queryPool = getQueryPool();
resetCommandBuffer->resetQueryPool(queryPool.getHandle(), mQuery, 1);
resetCommandBuffer->resetQueryPool(queryPool.getHandle(), mQuery, mQueryCount);
commandBuffer->beginQuery(queryPool.getHandle(), mQuery, 0);
}
......@@ -2866,14 +2897,14 @@ void QueryHelper::writeTimestampToPrimary(ContextVk *contextVk, PrimaryCommandBu
// Note that commands may not be flushed at this point.
const QueryPool &queryPool = getQueryPool();
primary->resetQueryPool(queryPool, mQuery, 1);
primary->resetQueryPool(queryPool, mQuery, mQueryCount);
primary->writeTimestamp(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, queryPool, mQuery);
}
void QueryHelper::writeTimestamp(ContextVk *contextVk, CommandBuffer *commandBuffer)
{
const QueryPool &queryPool = getQueryPool();
commandBuffer->resetQueryPool(queryPool.getHandle(), mQuery, 1);
commandBuffer->resetQueryPool(queryPool.getHandle(), mQuery, mQueryCount);
commandBuffer->writeTimestamp(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, queryPool.getHandle(),
mQuery);
// timestamp results are available immediately, retain this query so that we get its serial
......@@ -2897,11 +2928,8 @@ angle::Result QueryHelper::getUint64ResultNonBlocking(ContextVk *contextVk,
// wait forever and trigger GPU timeout.
if (hasSubmittedCommands())
{
VkDevice device = contextVk->getDevice();
constexpr VkQueryResultFlags kFlags = VK_QUERY_RESULT_64_BIT;
result =
getQueryPool().getResults(device, mQuery, 1, resultOut->getDataSize(),
resultOut->getPointerToResults(), sizeof(uint64_t), kFlags);
result = getResultImpl(contextVk, kFlags, resultOut);
}
else
{
......@@ -2927,11 +2955,8 @@ angle::Result QueryHelper::getUint64Result(ContextVk *contextVk, QueryResult *re
ASSERT(valid());
if (hasSubmittedCommands())
{
VkDevice device = contextVk->getDevice();
constexpr VkQueryResultFlags kFlags = VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT;
ANGLE_VK_TRY(contextVk, getQueryPool().getResults(
device, mQuery, 1, resultOut->getDataSize(),
resultOut->getPointerToResults(), sizeof(uint64_t), kFlags));
ANGLE_VK_TRY(contextVk, getResultImpl(contextVk, kFlags, resultOut));
}
else
{
......@@ -2940,6 +2965,24 @@ angle::Result QueryHelper::getUint64Result(ContextVk *contextVk, QueryResult *re
return angle::Result::Continue;
}
VkResult QueryHelper::getResultImpl(ContextVk *contextVk,
const VkQueryResultFlags flags,
QueryResult *resultOut)
{
std::array<uint64_t, 2 * gl::IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS> results;
VkDevice device = contextVk->getDevice();
VkResult result = getQueryPool().getResults(device, mQuery, mQueryCount, sizeof(results),
results.data(), sizeof(uint64_t), flags);
if (result == VK_SUCCESS)
{
resultOut->setResults(results.data(), mQueryCount);
}
return result;
}
// DynamicSemaphorePool implementation
DynamicSemaphorePool::DynamicSemaphorePool() = default;
......
......@@ -414,7 +414,7 @@ class DynamicQueryPool final : public DynamicallyGrowingPool<QueryPool>
angle::Result init(ContextVk *contextVk, VkQueryType type, uint32_t poolSize);
void destroy(VkDevice device);
angle::Result allocateQuery(ContextVk *contextVk, QueryHelper *queryOut);
angle::Result allocateQuery(ContextVk *contextVk, QueryHelper *queryOut, uint32_t queryCount);
void freeQuery(ContextVk *contextVk, QueryHelper *query);
const QueryPool &getQueryPool(size_t index) const { return mPools[index]; }
......@@ -439,12 +439,12 @@ class QueryResult final
}
size_t getDataSize() const { return mIntsPerResult * sizeof(uint64_t); }
void setResults(uint64_t *results, uint32_t queryCount);
uint64_t getResult(size_t index) const
{
ASSERT(index < mIntsPerResult);
return mResults[index];
}
uint64_t *getPointerToResults() { return mResults.data(); }
static constexpr size_t kDefaultResultIndex = 0;
static constexpr size_t kTransformFeedbackPrimitivesWrittenIndex = 0;
......@@ -455,7 +455,7 @@ class QueryResult final
std::array<uint64_t, 2> mResults;
};
// Queries in vulkan are identified by the query pool and an index for a query within that pool.
// Queries in Vulkan are identified by the query pool and an index for a query within that pool.
// Unlike other pools, such as descriptor pools where an allocation returns an independent object
// from the pool, the query allocations are not done through a Vulkan function and are only an
// integer index.
......@@ -463,7 +463,9 @@ class QueryResult final
// Furthermore, to support arbitrarily large number of queries, DynamicQueryPool creates query pools
// of a fixed size as needed and allocates indices within those pools.
//
// The QueryHelper class below keeps the pool and index pair together.
// The QueryHelper class below keeps the pool and index pair together. For multiview, multiple
// consecutive query indices are implicitly written to by the driver, so the query count is
// additionally kept.
class QueryHelper final : public Resource
{
public:
......@@ -473,7 +475,8 @@ class QueryHelper final : public Resource
QueryHelper &operator=(QueryHelper &&rhs);
void init(const DynamicQueryPool *dynamicQueryPool,
const size_t queryPoolIndex,
uint32_t query);
uint32_t query,
uint32_t queryCount);
void deinit();
bool valid() const { return mDynamicQueryPool != nullptr; }
......@@ -513,10 +516,14 @@ class QueryHelper final : public Resource
CommandBuffer *resetCommandBuffer,
CommandBuffer *commandBuffer);
void endQueryImpl(ContextVk *contextVk, CommandBuffer *commandBuffer);
VkResult getResultImpl(ContextVk *contextVk,
const VkQueryResultFlags flags,
QueryResult *resultOut);
const DynamicQueryPool *mDynamicQueryPool;
size_t mQueryPoolIndex;
uint32_t mQuery;
uint32_t mQueryCount;
};
// DynamicSemaphorePool allocates semaphores as needed. It uses a std::vector
......
......@@ -1440,9 +1440,6 @@ TEST_P(MultiviewOcclusionQueryTest, OcclusionQueryOnlyRightVisible)
ANGLE_SKIP_TEST_IF(!requestMultiviewExtension());
ANGLE_SKIP_TEST_IF(!requestOcclusionQueryExtension());
// TODO: fix occlusion queries with multiview on Vulkan. http://anglebug.com/6048
ANGLE_SKIP_TEST_IF(IsVulkan());
const std::string VS =
"#version 300 es\n"
"#extension " +
......
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