Commit b56ddbb7 by Yuly Novikov Committed by Commit Bot

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/1323849Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Commit-Queue: Yuly Novikov <ynovikov@chromium.org>
parent 526392dd
......@@ -650,8 +650,6 @@ angle::Result CommandGraph::submitCommands(Context *context,
previousBarrier, &mNodes[previousBarrierIndex + 1], afterNodesCount);
}
mLastBarrierIndex = kInvalidNodeIndex;
VkCommandBufferAllocateInfo primaryInfo = {};
primaryInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
primaryInfo.commandPool = commandPool->getHandle();
......@@ -715,12 +713,7 @@ angle::Result CommandGraph::submitCommands(Context *context,
ANGLE_VK_TRY(context, primaryCommandBufferOut->end());
// TODO(jmadill): Use pool allocation so we don't need to deallocate command graph.
for (CommandGraphNode *node : mNodes)
{
delete node;
}
mNodes.clear();
clear();
return angle::Result::Continue();
}
......@@ -730,6 +723,18 @@ bool CommandGraph::empty() const
return mNodes.empty();
}
void CommandGraph::clear()
{
mLastBarrierIndex = kInvalidNodeIndex;
// TODO(jmadill): Use pool allocator for performance. http://anglebug.com/2951
for (CommandGraphNode *node : mNodes)
{
delete node;
}
mNodes.clear();
}
// Dumps the command graph into a dot file that works with graphviz.
void CommandGraph::dumpGraphDotFile(std::ostream &out) const
{
......
......@@ -318,6 +318,7 @@ class CommandGraph final : angle::NonCopyable
CommandPool *commandPool,
CommandBuffer *primaryCommandBufferOut);
bool empty() const;
void clear();
CommandGraphNode *getLastBarrierNode(size_t *indexOut);
......
......@@ -1235,7 +1235,7 @@ void ContextVk::handleError(VkResult errorCode, const char *file, unsigned int l
if (errorCode == VK_ERROR_DEVICE_LOST)
{
mRenderer->markDeviceLost();
mRenderer->notifyDeviceLost();
}
mErrors->handleError(gl::Error(glErrorCode, glErrorCode, errorStream.str()));
......
......@@ -32,7 +32,7 @@ DisplayVk::~DisplayVk()
egl::Error DisplayVk::initialize(egl::Display *display)
{
ASSERT(mRenderer != nullptr && display != nullptr);
angle::Result result = mRenderer->initialize(this, display->getAttributeMap(), getWSIName());
angle::Result result = mRenderer->initialize(this, display, getWSIName());
ANGLE_TRY(angle::ToEGL(result, this, EGL_NOT_INITIALIZED));
return egl::NoError();
}
......@@ -196,7 +196,7 @@ void DisplayVk::handleError(VkResult result, const char *file, unsigned int line
if (result == VK_ERROR_DEVICE_LOST)
{
mRenderer->markDeviceLost();
mRenderer->notifyDeviceLost();
}
}
......
......@@ -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 @@ namespace
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 @@ void RendererVk::CommandBatch::destroy(VkDevice device)
// RendererVk implementation.
RendererVk::RendererVk()
: mCapsInitialized(false),
: mDisplay(nullptr),
mCapsInitialized(false),
mInstance(VK_NULL_HANDLE),
mEnableValidationLayers(false),
mEnableMockICD(false),
......@@ -368,9 +372,16 @@ void RendererVk::onDestroy(vk::Context *context)
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 @@ bool RendererVk::isDeviceLost() const
}
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 @@ void RendererVk::freeAllInFlightResources()
{
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 @@ angle::Result RendererVk::finishToSerial(vk::Context *context, Serial serial)
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 @@ angle::Result RendererVk::getTimestamp(vk::Context *context, uint64_t *timestamp
// 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
......
......@@ -24,7 +24,7 @@
namespace egl
{
class AttributeMap;
class Display;
class BlobCache;
}
......@@ -44,12 +44,10 @@ class RendererVk : angle::NonCopyable
RendererVk();
~RendererVk();
angle::Result initialize(DisplayVk *displayVk,
const egl::AttributeMap &attribs,
const char *wsiName);
angle::Result initialize(DisplayVk *displayVk, egl::Display *display, const char *wsiName);
void onDestroy(vk::Context *context);
void markDeviceLost();
void notifyDeviceLost();
bool isDeviceLost() const;
std::string getVendorString() const;
......@@ -222,6 +220,8 @@ class RendererVk : angle::NonCopyable
angle::Result checkCompletedGpuEvents(vk::Context *context);
void flushGpuEvents(double nextSyncGpuTimestampS, double nextSyncCpuTimestampS);
egl::Display *mDisplay;
mutable bool mCapsInitialized;
mutable gl::Caps mNativeCaps;
mutable gl::TextureCapsMap mNativeTextureCaps;
......
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