Commit 428e4415 by Tobin Ehlis Committed by Commit Bot

Vulkan: Migrate trace events and occlusion queries

Moved GPU trace event and occlusion query commands that were on the primary command buffer to the SecondaryCommandBuffer (SCB). Putting these commands on outside render pass SCB and flushing those commands to primary on-demand as needed to maintain ordering of commands. For resetQueryPool command used by occlusion query, allow the SCB to queue up that command for inside RenderPass SCB. This avoids ending a renderPass prematurely and allows all outstanding reset commands to be executed before the beginRenderPass command since the resets must occur outside of a renderPass. This is groundwork to simplify the hand-off of SCBs from the main thread to a worker thread. Long-term we'd like a single SCB that can handle both inside and outside renderPass commands at the same time to pass to the worker thread for processing into a primary CB. Bug: b/154030403 Bug: angleproject:4603 Change-Id: Ic1023ae27a9b14435743549ea9933edf1c4b318b Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2168114Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com> Reviewed-by: 's avatarCharlie Lao <cclao@google.com> Commit-Queue: Tobin Ehlis <tobine@google.com>
parent 2aa99c12
......@@ -861,7 +861,8 @@ angle::Result ContextVk::initialize()
mPrimaryBufferCounter++;
EventName eventName = GetTraceEventName("Primary", mPrimaryBufferCounter);
ANGLE_TRY(traceGpuEvent(&mPrimaryCommands, TRACE_EVENT_PHASE_BEGIN, eventName));
ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands.getCommandBuffer(),
TRACE_EVENT_PHASE_BEGIN, eventName));
}
return angle::Result::Continue;
......@@ -1764,7 +1765,7 @@ angle::Result ContextVk::synchronizeCpuGpuTime()
return angle::Result::Continue;
}
angle::Result ContextVk::traceGpuEventImpl(vk::PrimaryCommandBuffer *commandBuffer,
angle::Result ContextVk::traceGpuEventImpl(vk::CommandBuffer *commandBuffer,
char phase,
const EventName &name)
{
......@@ -3821,17 +3822,18 @@ angle::Result ContextVk::flushImpl(const vk::Semaphore *signalSemaphore)
memoryBarrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
memoryBarrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
mPrimaryCommands.memoryBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_HOST_BIT, &memoryBarrier);
mOutsideRenderPassCommands.getCommandBuffer().memoryBarrier(
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_HOST_BIT, &memoryBarrier);
mIsAnyHostVisibleBufferWritten = false;
}
if (mGpuEventsEnabled)
{
EventName eventName = GetTraceEventName("Primary", mPrimaryBufferCounter);
ANGLE_TRY(traceGpuEvent(&mPrimaryCommands, TRACE_EVENT_PHASE_END, eventName));
ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands.getCommandBuffer(),
TRACE_EVENT_PHASE_END, eventName));
}
flushOutsideRenderPassCommands();
ANGLE_VK_TRY(this, mPrimaryCommands.end());
// Free secondary command pool allocations and restart command buffers with the new page.
......@@ -3861,7 +3863,8 @@ angle::Result ContextVk::flushImpl(const vk::Semaphore *signalSemaphore)
if (mGpuEventsEnabled)
{
EventName eventName = GetTraceEventName("Primary", mPrimaryBufferCounter);
ANGLE_TRY(traceGpuEvent(&mPrimaryCommands, TRACE_EVENT_PHASE_BEGIN, eventName));
ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands.getCommandBuffer(),
TRACE_EVENT_PHASE_BEGIN, eventName));
}
return angle::Result::Continue;
......@@ -4227,13 +4230,13 @@ ANGLE_INLINE angle::Result ContextVk::startRenderPass(gl::Rectangle renderArea)
ANGLE_TRY(mDrawFramebuffer->startNewRenderPass(this, renderArea, &mRenderPassCommandBuffer));
if (mActiveQueryAnySamples)
{
mActiveQueryAnySamples->getQueryHelper()->beginOcclusionQuery(this, &mPrimaryCommands,
mActiveQueryAnySamples->getQueryHelper()->beginOcclusionQuery(this,
mRenderPassCommandBuffer);
}
if (mActiveQueryAnySamplesConservative)
{
mActiveQueryAnySamplesConservative->getQueryHelper()->beginOcclusionQuery(
this, &mPrimaryCommands, mRenderPassCommandBuffer);
this, mRenderPassCommandBuffer);
}
return angle::Result::Continue;
}
......@@ -4266,7 +4269,9 @@ angle::Result ContextVk::endRenderPass()
mRenderPassCounter++;
EventName eventName = GetTraceEventName("RP", mRenderPassCounter);
ANGLE_TRY(traceGpuEvent(&mPrimaryCommands, TRACE_EVENT_PHASE_BEGIN, eventName));
ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands.getCommandBuffer(),
TRACE_EVENT_PHASE_BEGIN, eventName));
flushOutsideRenderPassCommands();
}
mRenderPassCommands.pauseTransformFeedbackIfStarted();
......@@ -4277,7 +4282,9 @@ angle::Result ContextVk::endRenderPass()
if (mGpuEventsEnabled)
{
EventName eventName = GetTraceEventName("RP", mRenderPassCounter);
ANGLE_TRY(traceGpuEvent(&mPrimaryCommands, TRACE_EVENT_PHASE_END, eventName));
ANGLE_TRY(traceGpuEvent(&mOutsideRenderPassCommands.getCommandBuffer(),
TRACE_EVENT_PHASE_END, eventName));
flushOutsideRenderPassCommands();
}
return angle::Result::Continue;
......@@ -4383,8 +4390,7 @@ void ContextVk::beginOcclusionQuery(QueryVk *queryVk)
// not yet started, we just remember it and defer the start call.
if (mRenderPassCommands.started())
{
queryVk->getQueryHelper()->beginOcclusionQuery(this, &mPrimaryCommands,
mRenderPassCommandBuffer);
queryVk->getQueryHelper()->beginOcclusionQuery(this, mRenderPassCommandBuffer);
}
if (queryVk->isAnySamplesQuery())
{
......@@ -4629,8 +4635,9 @@ angle::Result RenderPassCommandBuffer::flushToPrimary(ContextVk *contextVk,
{
addRenderPassCommandDiagnostics(contextVk);
}
// Commands that are added to primary before beginRenderPass command
executeBarriers(primary);
mCommandBuffer.executeQueuedResetQueryPoolCommands(primary->getHandle());
// Pull a RenderPass from the cache.
RenderPassCache &renderPassCache = contextVk->getRenderPassCache();
......
......@@ -585,7 +585,7 @@ class ContextVk : public ContextImpl, public vk::Context
// Create Begin/End/Instant GPU trace events, which take their timestamps from GPU queries.
// The events are queued until the query results are available. Possible values for `phase`
// are TRACE_EVENT_PHASE_*
ANGLE_INLINE angle::Result traceGpuEvent(vk::PrimaryCommandBuffer *commandBuffer,
ANGLE_INLINE angle::Result traceGpuEvent(vk::CommandBuffer *commandBuffer,
char phase,
const EventName &name)
{
......@@ -935,7 +935,7 @@ class ContextVk : public ContextImpl, public vk::Context
angle::Result memoryBarrierImpl(GLbitfield barriers, VkPipelineStageFlags stageMask);
angle::Result synchronizeCpuGpuTime();
angle::Result traceGpuEventImpl(vk::PrimaryCommandBuffer *commandBuffer,
angle::Result traceGpuEventImpl(vk::CommandBuffer *commandBuffer,
char phase,
const EventName &name);
angle::Result checkCompletedGpuEvents();
......
......@@ -131,6 +131,16 @@ ANGLE_INLINE const CommandHeader *NextCommand(const CommandHeader *command)
command->size);
}
// Add any queued resetQueryPool commands to the given cmdBuffer
void SecondaryCommandBuffer::executeQueuedResetQueryPoolCommands(VkCommandBuffer cmdBuffer)
{
for (const ResetQueryPoolParams &queryParams : mResetQueryQueue)
{
vkCmdResetQueryPool(cmdBuffer, queryParams.queryPool, queryParams.firstQuery,
queryParams.queryCount);
}
}
// Parse the cmds in this cmd buffer into given primary cmd buffer
void SecondaryCommandBuffer::executeCommands(VkCommandBuffer cmdBuffer)
{
......
......@@ -615,6 +615,9 @@ class SecondaryCommandBuffer final : angle::NonCopyable
void resetEvent(VkEvent event, VkPipelineStageFlags stageMask);
// Store up resetQueryPool command and prepend to commands when executing
void queueResetQueryPool(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount);
void resetQueryPool(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount);
void resolveImage(const Image &srcImage,
......@@ -646,6 +649,9 @@ class SecondaryCommandBuffer final : angle::NonCopyable
// Parse the cmds in this cmd buffer into given primary cmd buffer for execution
void executeCommands(VkCommandBuffer cmdBuffer);
// If resetQueryPoolCommands are queued, call this to execute them all
// This should only be called on a cmdBuffer without an active renderPass
void executeQueuedResetQueryPoolCommands(VkCommandBuffer cmdBuffer);
// Calculate memory usage of this command buffer for diagnostics.
void getMemoryUsageStats(size_t *usedMemoryOut, size_t *allocatedMemoryOut) const;
......@@ -673,6 +679,7 @@ class SecondaryCommandBuffer final : angle::NonCopyable
{
mCommands.clear();
initialize(mAllocator);
mResetQueryQueue.clear();
}
// This will cause the SecondaryCommandBuffer to become invalid by clearing its allocator
......@@ -777,6 +784,9 @@ class SecondaryCommandBuffer final : angle::NonCopyable
uint8_t *mCurrentWritePointer;
size_t mCurrentBytesRemaining;
// resetQueryPool command must be executed outside RP so we queue them up for
// an inside RenderPass command buffer and pre-prend them to the commands
std::vector<ResetQueryPoolParams> mResetQueryQueue;
};
ANGLE_INLINE SecondaryCommandBuffer::SecondaryCommandBuffer()
......@@ -1303,6 +1313,13 @@ ANGLE_INLINE void SecondaryCommandBuffer::resetEvent(VkEvent event, VkPipelineSt
paramStruct->stageMask = stageMask;
}
ANGLE_INLINE void SecondaryCommandBuffer::queueResetQueryPool(VkQueryPool queryPool,
uint32_t firstQuery,
uint32_t queryCount)
{
mResetQueryQueue.push_back({queryPool, firstQuery, queryCount});
}
ANGLE_INLINE void SecondaryCommandBuffer::resetQueryPool(VkQueryPool queryPool,
uint32_t firstQuery,
uint32_t queryCount)
......
......@@ -1187,6 +1187,13 @@ void QueryHelper::deinit()
mMostRecentSerial = Serial();
}
void QueryHelper::resetQueryPool(ContextVk *contextVk,
CommandBuffer *outsideRenderPassCommandBuffer)
{
const QueryPool &queryPool = getQueryPool();
outsideRenderPassCommandBuffer->resetQueryPool(queryPool.getHandle(), mQuery, 1);
}
angle::Result QueryHelper::beginQuery(ContextVk *contextVk)
{
vk::CommandBuffer *outsideRenderPassCommandBuffer;
......@@ -1207,13 +1214,10 @@ angle::Result QueryHelper::endQuery(ContextVk *contextVk)
return angle::Result::Continue;
}
void QueryHelper::beginOcclusionQuery(ContextVk *contextVk,
PrimaryCommandBuffer *primaryCommands,
CommandBuffer *renderPassCommandBuffer)
void QueryHelper::beginOcclusionQuery(ContextVk *contextVk, CommandBuffer *renderPassCommandBuffer)
{
const QueryPool &queryPool = getQueryPool();
// reset has to be encoded in primary command buffer per spec
primaryCommands->resetQueryPool(queryPool, mQuery, 1);
renderPassCommandBuffer->queueResetQueryPool(queryPool.getHandle(), mQuery, 1);
renderPassCommandBuffer->beginQuery(queryPool.getHandle(), mQuery, 0);
mMostRecentSerial = contextVk->getCurrentQueueSerial();
}
......
......@@ -396,9 +396,9 @@ class QueryHelper final
angle::Result endQuery(ContextVk *contextVk);
// for occlusion query
void beginOcclusionQuery(ContextVk *contextVk,
PrimaryCommandBuffer *primaryCommands,
CommandBuffer *renderPassCommandBuffer);
// Must resetQueryPool outside of RenderPass before beginning occlusion query.
void resetQueryPool(ContextVk *contextVk, CommandBuffer *outsideRenderPassCommandBuffer);
void beginOcclusionQuery(ContextVk *contextVk, CommandBuffer *renderPassCommandBuffer);
void endOcclusionQuery(ContextVk *contextVk, CommandBuffer *renderPassCommandBuffer);
angle::Result flushAndWriteTimestamp(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