Don't forward device lost errors to the uncaptured error callback

This issue was discovered in http://crrev.com/c/2613517 where a
device lost error on page teardown was bubbling up to the Renderer's
uncaptured error callback.

Bug: chromium:1160459
Change-Id: I64b8c7779f4808d5a4b87c131aaf2e041c512bb9
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/36960
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
This commit is contained in:
Austin Eng
2021-01-13 17:53:29 +00:00
committed by Commit Bot service account
parent 558599fc9a
commit 8ef94f1684
5 changed files with 52 additions and 10 deletions

View File

@@ -212,10 +212,15 @@ namespace dawn_native {
}
void DeviceBase::HandleError(InternalErrorType type, const char* message) {
// If we receive an internal error, assume the backend can't recover and proceed with
// device destruction. We first wait for all previous commands to be completed so that
// backend objects can be freed immediately, before handling the loss.
if (type == InternalErrorType::Internal) {
if (type == InternalErrorType::DeviceLost) {
// A real device lost happened. Set the state to disconnected as the device cannot be
// used.
mState = State::Disconnected;
} else if (type == InternalErrorType::Internal) {
// If we receive an internal error, assume the backend can't recover and proceed with
// device destruction. We first wait for all previous commands to be completed so that
// backend objects can be freed immediately, before handling the loss.
// Move away from the Alive state so that the application cannot use this device
// anymore.
// TODO(cwallez@chromium.org): Do we need atomics for this to become visible to other
@@ -240,7 +245,7 @@ namespace dawn_native {
mDeviceLostCallback = nullptr;
}
// Still forward device loss and internal errors to the error scopes so they all reject.
// Still forward device loss errors to the error scopes so they all reject.
mCurrentErrorScope->HandleError(ToWGPUErrorType(type), message);
}
@@ -322,7 +327,7 @@ namespace dawn_native {
if (DAWN_LIKELY(mState == State::Alive)) {
return {};
}
return DAWN_DEVICE_LOST_ERROR("Device is lost");
return DAWN_VALIDATION_ERROR("Device is lost");
}
void DeviceBase::LoseForTesting() {

View File

@@ -26,7 +26,6 @@ namespace dawn_native {
Validation,
DeviceLost,
Internal,
Unimplemented,
OutOfMemory
};
@@ -72,11 +71,23 @@ namespace dawn_native {
#define DAWN_MAKE_ERROR(TYPE, MESSAGE) \
::dawn_native::ErrorData::Create(TYPE, MESSAGE, __FILE__, __func__, __LINE__)
#define DAWN_VALIDATION_ERROR(MESSAGE) DAWN_MAKE_ERROR(InternalErrorType::Validation, MESSAGE)
// DAWN_DEVICE_LOST_ERROR means that there was a real unrecoverable native device lost error.
// We can't even do a graceful shutdown because the Device is gone.
#define DAWN_DEVICE_LOST_ERROR(MESSAGE) DAWN_MAKE_ERROR(InternalErrorType::DeviceLost, MESSAGE)
// DAWN_INTERNAL_ERROR means Dawn hit an unexpected error in the backend and should try to
// gracefully shut down.
#define DAWN_INTERNAL_ERROR(MESSAGE) DAWN_MAKE_ERROR(InternalErrorType::Internal, MESSAGE)
#define DAWN_UNIMPLEMENTED_ERROR(MESSAGE) \
DAWN_MAKE_ERROR(InternalErrorType::Internal, std::string("Unimplemented: ") + MESSAGE)
// DAWN_OUT_OF_MEMORY_ERROR means we ran out of memory. It may be used as a signal internally in
// Dawn to free up unused resources. Or, it may bubble up to the application to signal an allocation
// was too large or they should free some existing resources.
#define DAWN_OUT_OF_MEMORY_ERROR(MESSAGE) DAWN_MAKE_ERROR(InternalErrorType::OutOfMemory, MESSAGE)
#define DAWN_CONCAT1(x, y) x##y

View File

@@ -87,14 +87,23 @@ namespace dawn_native {
consumed = true;
break;
// Unknown and DeviceLost are fatal. All error scopes capture them.
// DeviceLost is fatal. All error scopes capture them.
// |consumed| is false because these should bubble to all scopes.
case wgpu::ErrorType::Unknown:
case wgpu::ErrorType::DeviceLost:
consumed = false;
if (currentScope->mErrorType != wgpu::ErrorType::DeviceLost) {
// DeviceLost overrides any other error that is not a DeviceLost.
currentScope->mErrorType = type;
currentScope->mErrorMessage = message;
}
break;
case wgpu::ErrorType::Unknown:
// Means the scope was destroyed before contained work finished.
// This happens when you destroy the device while there's pending work.
// That's handled in ErrorScope::UnlinkForShutdownImpl, not here.
case wgpu::ErrorType::NoError:
// Not considered an error, and should never be passed to HandleError.
UNREACHABLE();
return;
}
@@ -111,8 +120,10 @@ namespace dawn_native {
}
// The root error scope captures all uncaptured errors.
// Except, it should not capture device lost errors since those go to
// the device lost callback.
ASSERT(currentScope->IsRoot());
if (currentScope->mCallback) {
if (currentScope->mCallback && type != wgpu::ErrorType::DeviceLost) {
currentScope->mCallback(static_cast<WGPUErrorType>(type), message,
currentScope->mUserdata);
}