Commit e86b4257 by Jamie Madill Committed by Commit Bot

Vulkan: Refactor how finishToSerial() retires commands.

This cleans up some of the logic around command completion. We no longer query each Fence in order after a finishToSerial call. Instead we clear out all the commands that have been completed up to the latest Fence. Also cleans up ordering code. Because we now have a linear ordering of Serials we can validate the ordering is "good". Attempt at solving a suspicious ASSERT firing on AMD Win7. Bug: angleproject:5198 Change-Id: I7750eff7f8d3aff397e7880f997ad86c9bf7d7a8 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2490342 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com>
parent cb5c0b01
...@@ -309,6 +309,21 @@ vk::ResourceAccess GetStencilAccess(const gl::DepthStencilState &dsState) ...@@ -309,6 +309,21 @@ vk::ResourceAccess GetStencilAccess(const gl::DepthStencilState &dsState)
return dsState.isStencilNoOp() && dsState.isStencilBackNoOp() ? vk::ResourceAccess::ReadOnly return dsState.isStencilNoOp() && dsState.isStencilBackNoOp() ? vk::ResourceAccess::ReadOnly
: vk::ResourceAccess::Write; : vk::ResourceAccess::Write;
} }
bool CommandsHaveValidOrdering(const std::vector<vk::CommandBatch> &commands)
{
Serial currentSerial;
for (const vk::CommandBatch &commands : commands)
{
if (commands.serial <= currentSerial)
{
return false;
}
currentSerial = commands.serial;
}
return true;
}
} // anonymous namespace } // anonymous namespace
ANGLE_INLINE void ContextVk::flushDescriptorSetUpdates() ANGLE_INLINE void ContextVk::flushDescriptorSetUpdates()
...@@ -398,14 +413,33 @@ angle::Result CommandQueue::checkCompletedCommands(vk::Context *context) ...@@ -398,14 +413,33 @@ angle::Result CommandQueue::checkCompletedCommands(vk::Context *context)
break; break;
} }
ANGLE_VK_TRY(context, result); ANGLE_VK_TRY(context, result);
++finishedCount;
}
renderer->onCompletedSerial(batch.serial); if (finishedCount == 0)
{
return angle::Result::Continue;
}
return retireFinishedCommands(context, finishedCount);
}
angle::Result CommandQueue::retireFinishedCommands(vk::Context *context, size_t finishedCount)
{
ASSERT(finishedCount > 0);
RendererVk *renderer = context->getRenderer();
VkDevice device = renderer->getDevice();
for (size_t commandIndex = 0; commandIndex < finishedCount; ++commandIndex)
{
vk::CommandBatch &batch = mInFlightCommands[commandIndex];
renderer->onCompletedSerial(batch.serial);
renderer->resetSharedFence(&batch.fence); renderer->resetSharedFence(&batch.fence);
ANGLE_TRACE_EVENT0("gpu.angle", "command buffer recycling"); ANGLE_TRACE_EVENT0("gpu.angle", "command buffer recycling");
batch.commandPool.destroy(device); batch.commandPool.destroy(device);
ANGLE_TRY(releasePrimaryCommandBuffer(context, std::move(batch.primaryCommands))); ANGLE_TRY(releasePrimaryCommandBuffer(context, std::move(batch.primaryCommands)));
++finishedCount;
} }
if (finishedCount > 0) if (finishedCount > 0)
...@@ -520,7 +554,9 @@ bool CommandQueue::hasInFlightCommands() const ...@@ -520,7 +554,9 @@ bool CommandQueue::hasInFlightCommands() const
return !mInFlightCommands.empty(); return !mInFlightCommands.empty();
} }
angle::Result CommandQueue::finishToSerial(vk::Context *context, Serial serial, uint64_t timeout) angle::Result CommandQueue::finishToSerial(vk::Context *context,
Serial finishSerial,
uint64_t timeout)
{ {
ASSERT(!context->getRenderer()->getFeatures().asynchronousCommandProcessing.enabled); ASSERT(!context->getRenderer()->getFeatures().asynchronousCommandProcessing.enabled);
...@@ -528,28 +564,33 @@ angle::Result CommandQueue::finishToSerial(vk::Context *context, Serial serial, ...@@ -528,28 +564,33 @@ angle::Result CommandQueue::finishToSerial(vk::Context *context, Serial serial,
{ {
return angle::Result::Continue; return angle::Result::Continue;
} }
ANGLE_TRACE_EVENT0("gpu.angle", "CommandQueue::finishToSerial"); ANGLE_TRACE_EVENT0("gpu.angle", "CommandQueue::finishToSerial");
// Find the first batch with serial equal to or bigger than given serial (note that
// the batch serials are unique, otherwise upper-bound would have been necessary). // Find the serial in the the list. The serials should be in order.
// ASSERT(CommandsHaveValidOrdering(mInFlightCommands));
// Note: we don't check for the exact serial, because it may belong to another context. For
// example, imagine the following submissions: size_t finishedCount = 0;
// while (finishedCount < mInFlightCommands.size() &&
// - Context 1: Serial 1, Serial 3, Serial 5 mInFlightCommands[finishedCount].serial < finishSerial)
// - Context 2: Serial 2, Serial 4, Serial 6
//
// And imagine none of the submissions have finished yet. Now if Context 2 asks for
// finishToSerial(3), it will have no choice but to finish until Serial 4 instead.
size_t batchIndex = mInFlightCommands.size() - 1;
for (size_t i = 0; i < mInFlightCommands.size(); ++i)
{ {
if (mInFlightCommands[i].serial >= serial) finishedCount++;
}
// This heuristic attempts to increase chances of success for shared resource scenarios.
// Ultimately as long as fences are managed by ContextVk there are edge case bugs here.
// TODO: http://anglebug.com/5217: fix this bug by moving it submit into RendererVk.
if (finishedCount < mInFlightCommands.size())
{ {
batchIndex = i; finishedCount++;
break;
} }
if (finishedCount == 0)
{
return angle::Result::Continue;
} }
const vk::CommandBatch &batch = mInFlightCommands[batchIndex];
const vk::CommandBatch &batch = mInFlightCommands[finishedCount - 1];
// Wait for it finish // Wait for it finish
VkDevice device = context->getDevice(); VkDevice device = context->getDevice();
...@@ -558,7 +599,7 @@ angle::Result CommandQueue::finishToSerial(vk::Context *context, Serial serial, ...@@ -558,7 +599,7 @@ angle::Result CommandQueue::finishToSerial(vk::Context *context, Serial serial,
ANGLE_VK_TRY(context, status); ANGLE_VK_TRY(context, status);
// Clean up finished batches. // Clean up finished batches.
return checkCompletedCommands(context); return retireFinishedCommands(context, finishedCount);
} }
angle::Result CommandQueue::submitFrame(vk::Context *context, angle::Result CommandQueue::submitFrame(vk::Context *context,
......
...@@ -53,7 +53,7 @@ class CommandQueue final : angle::NonCopyable ...@@ -53,7 +53,7 @@ class CommandQueue final : angle::NonCopyable
void clearAllGarbage(RendererVk *renderer); void clearAllGarbage(RendererVk *renderer);
angle::Result finishToSerial(vk::Context *context, Serial serial, uint64_t timeout); angle::Result finishToSerial(vk::Context *context, Serial finishSerial, uint64_t timeout);
angle::Result submitFrame(vk::Context *context, angle::Result submitFrame(vk::Context *context,
egl::ContextPriority priority, egl::ContextPriority priority,
...@@ -76,6 +76,7 @@ class CommandQueue final : angle::NonCopyable ...@@ -76,6 +76,7 @@ class CommandQueue final : angle::NonCopyable
vk::PrimaryCommandBuffer &&commandBuffer, vk::PrimaryCommandBuffer &&commandBuffer,
vk::CommandPool *commandPool, vk::CommandPool *commandPool,
vk::CommandBatch *batch); vk::CommandBatch *batch);
angle::Result retireFinishedCommands(vk::Context *context, size_t finishedCount);
vk::GarbageQueue mGarbageQueue; vk::GarbageQueue mGarbageQueue;
std::vector<vk::CommandBatch> mInFlightCommands; std::vector<vk::CommandBatch> mInFlightCommands;
......
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