Commit 83c24aa8 by Jamie Madill Committed by Commit Bot

Vulkan: Reference Context fences in FenceSyncVk.

A particular test waits on a fence that was created in another Context. Then it immediately destroys all other resources. This triggered a bug where the VkEvent corresponding to the FenceSync was deleted while it was still in use by a command buffer. Fix this by referencing the other submit fence of the second ContextVk in the FenceSync class. Bug: angleproject:2464 Change-Id: I4ef096bf760aa8943db08d491006c68e36db993b Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1757505Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 0aa11026
......@@ -28,7 +28,10 @@ void FenceSyncVk::onDestroy(ContextVk *contextVk)
contextVk->releaseObject(contextVk->getCurrentQueueSerial(), &mEvent);
}
mFence.reset(contextVk->getDevice());
for (vk::Shared<vk::Fence> &fence : mFences)
{
fence.reset(contextVk->getDevice());
}
}
void FenceSyncVk::onDestroy(DisplayVk *display)
......@@ -36,7 +39,7 @@ void FenceSyncVk::onDestroy(DisplayVk *display)
std::vector<vk::GarbageObjectBase> garbage;
mEvent.dumpResources(&garbage);
display->getRenderer()->addGarbage(std::move(mFence), std::move(garbage));
display->getRenderer()->addGarbage(std::move(mFences), std::move(garbage));
}
angle::Result FenceSyncVk::initialize(ContextVk *contextVk)
......@@ -53,9 +56,11 @@ angle::Result FenceSyncVk::initialize(ContextVk *contextVk)
vk::Scoped<vk::Event> event(device);
ANGLE_VK_TRY(contextVk, event.get().init(device, eventCreateInfo));
ANGLE_TRY(contextVk->getNextSubmitFence(&mFence));
vk::Shared<vk::Fence> fence;
ANGLE_TRY(contextVk->getNextSubmitFence(&fence));
mEvent = event.release();
mFences.emplace_back(std::move(fence));
contextVk->getCommandGraph()->setFenceSync(mEvent);
return angle::Result::Continue;
......@@ -91,8 +96,9 @@ angle::Result FenceSyncVk::clientWait(vk::Context *context,
}
// Wait on the fence that's expected to be signaled on the first vkQueueSubmit after
// `initialize` was called.
VkResult status = mFence.get().wait(renderer->getDevice(), timeout);
// `initialize` was called. The first fence is the fence created to signal this sync.
ASSERT(!mFences.empty());
VkResult status = mFences[0].get().wait(renderer->getDevice(), timeout);
// Check for errors, but don't consider timeout as such.
if (status != VK_TIMEOUT)
......@@ -109,6 +115,11 @@ angle::Result FenceSyncVk::serverWait(vk::Context *context, ContextVk *contextVk
if (contextVk)
{
contextVk->getCommandGraph()->waitFenceSync(mEvent);
// Track fences from Contexts that use this sync for garbage collection.
vk::Shared<vk::Fence> nextSubmitFence;
ANGLE_TRY(contextVk->getNextSubmitFence(&nextSubmitFence));
mFences.emplace_back(std::move(nextSubmitFence));
}
return angle::Result::Continue;
}
......
......@@ -46,9 +46,9 @@ class FenceSyncVk
// The vkEvent that's signaled on `init` and can be waited on in `serverWait`, or queried with
// `getStatus`.
vk::Event mEvent;
// The vkFence that's signaled once the command buffer including the `init` signal is executed.
// `clientWait` waits on this fence.
vk::Shared<vk::Fence> mFence;
// The first fence in the list is signaled once the CB including the `init` signal is executed.
// `clientWait` waits on this fence. The other fences are referenced to prevent deletion.
std::vector<vk::Shared<vk::Fence>> mFences;
};
class SyncVk final : public SyncImpl
......
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