Vulkan: Handle VK_ERROR_DEVICE_LOST
By notifying egl::Display that the device is lost,
which marks all gl::Context as lost,
turning all future GL commands to no-ops.
Also clear CommandGraph and destroy in flight resources,
making sure no more commands are executed on the lost device.
Bug: angleproject:2657
Change-Id: I3a1e3646c8ebb37faff507a3c5cec7582a7e05fc
Reviewed-on: https://chromium-review.googlesource.com/c/1323849
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Commit-Queue: Yuly Novikov <ynovikov@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/RendererVk.cpp b/src/libANGLE/renderer/vulkan/RendererVk.cpp
index 6f17445..03cc234 100644
--- a/src/libANGLE/renderer/vulkan/RendererVk.cpp
+++ b/src/libANGLE/renderer/vulkan/RendererVk.cpp
@@ -16,6 +16,7 @@
#include "common/debug.h"
#include "common/system_utils.h"
+#include "libANGLE/Display.h"
#include "libANGLE/renderer/driver_utils.h"
#include "libANGLE/renderer/vulkan/CommandGraph.h"
#include "libANGLE/renderer/vulkan/CompilerVk.h"
@@ -49,6 +50,8 @@
constexpr size_t kUniformBufferDescriptorsPerDescriptorSet = 2;
// Update the pipeline cache every this many swaps (if 60fps, this means every 10 minutes)
static constexpr uint32_t kPipelineCacheVkUpdatePeriod = 10 * 60 * 60;
+// Wait a maximum of 10s. If that times out, we declare it a failure.
+static constexpr uint64_t kMaxFenceWaitTimeNs = 10'000'000'000llu;
bool ShouldEnableMockICD(const egl::AttributeMap &attribs)
{
@@ -294,7 +297,8 @@
// RendererVk implementation.
RendererVk::RendererVk()
- : mCapsInitialized(false),
+ : mDisplay(nullptr),
+ mCapsInitialized(false),
mInstance(VK_NULL_HANDLE),
mEnableValidationLayers(false),
mEnableMockICD(false),
@@ -368,9 +372,16 @@
mPhysicalDevice = VK_NULL_HANDLE;
}
-void RendererVk::markDeviceLost()
+void RendererVk::notifyDeviceLost()
{
mDeviceLost = true;
+
+ mCommandGraph.clear();
+ mLastSubmittedQueueSerial = mCurrentQueueSerial;
+ mCurrentQueueSerial = mQueueSerialFactory.generate();
+ freeAllInFlightResources();
+
+ mDisplay->notifyDeviceLost();
}
bool RendererVk::isDeviceLost() const
@@ -379,9 +390,11 @@
}
angle::Result RendererVk::initialize(DisplayVk *displayVk,
- const egl::AttributeMap &attribs,
+ egl::Display *display,
const char *wsiName)
{
+ mDisplay = display;
+ const egl::AttributeMap &attribs = mDisplay->getAttributeMap();
ScopedVkLoaderEnvironment scopedEnvironment(ShouldUseDebugLayers(attribs),
ShouldEnableMockICD(attribs));
mEnableValidationLayers = scopedEnvironment.canEnableValidationLayers();
@@ -933,6 +946,13 @@
{
for (CommandBatch &batch : mInFlightCommands)
{
+ // On device loss we need to wait for fence to be signaled before destroying it
+ if (mDeviceLost)
+ {
+ VkResult status = batch.fence.wait(mDevice, kMaxFenceWaitTimeNs);
+ // If wait times out, it is probably not possible to recover from lost device
+ ASSERT(status == VK_SUCCESS || status == VK_ERROR_DEVICE_LOST);
+ }
batch.fence.destroy(mDevice);
batch.commandPool.destroy(mDevice);
}
@@ -1063,8 +1083,6 @@
const CommandBatch &batch = mInFlightCommands[batchIndex];
// Wait for it finish
- constexpr uint64_t kMaxFenceWaitTimeNs = 10'000'000'000llu;
- // Wait a maximum of 10s. If that times out, we declare it a failure.
ANGLE_VK_TRY(context, batch.fence.wait(mDevice, kMaxFenceWaitTimeNs));
// Clean up finished batches.
@@ -1335,8 +1353,6 @@
// Wait for the submission to finish. Given no semaphores, there is hope that it would execute
// in parallel with what's already running on the GPU.
- // Declare it a failure if it times out.
- constexpr uint64_t kMaxFenceWaitTimeNs = 10'000'000'000llu;
ANGLE_VK_TRY(context, fence.get().wait(mDevice, kMaxFenceWaitTimeNs));
// Get the query results