blob: 1740a47a6291c4fd0cbab38fd9d84ca251efa948 [file] [log] [blame]
/*
* Copyright 2023 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/graphite/dawn/DawnErrorChecker.h"
#include "include/private/base/SkAssert.h"
#include "src/gpu/graphite/Log.h"
#include "src/gpu/graphite/dawn/DawnAsyncWait.h"
namespace skgpu::graphite {
namespace {
constexpr const char* kErrorScopeNames[] = {"validation", "out-of-memory", "internal"};
constexpr DawnErrorType kErrorScopeTypes[] = {
DawnErrorType::kValidation, DawnErrorType::kOutOfMemory, DawnErrorType::kInternal};
static_assert(std::size(kErrorScopeNames) == std::size(kErrorScopeTypes));
constexpr int kScopeCount = std::size(kErrorScopeTypes);
} // namespace
DawnErrorChecker::DawnErrorChecker(const wgpu::Device& device) : fArmed(true), fDevice(device) {
fDevice.PushErrorScope(wgpu::ErrorFilter::Validation);
fDevice.PushErrorScope(wgpu::ErrorFilter::OutOfMemory);
fDevice.PushErrorScope(wgpu::ErrorFilter::Internal);
}
DawnErrorChecker::~DawnErrorChecker() {
[[maybe_unused]] auto err = this->popErrorScopes();
SkASSERT(!fArmed);
SkASSERT(err == DawnErrorType::kNoError);
}
SkEnumBitMask<DawnErrorType> DawnErrorChecker::popErrorScopes() {
if (!fArmed) {
return DawnErrorType::kNoError;
}
struct ErrorState {
SkEnumBitMask<DawnErrorType> fError;
int fScopeIdx;
DawnAsyncWait fWait;
ErrorState(const wgpu::Device& device)
: fError(DawnErrorType::kNoError), fScopeIdx(kScopeCount - 1), fWait(device) {}
} errorState(fDevice);
wgpu::ErrorCallback errorCallback = [](WGPUErrorType status, const char* msg, void* userData) {
ErrorState* errorState = static_cast<ErrorState*>(userData);
if (status != WGPUErrorType_NoError) {
SkASSERT(errorState->fScopeIdx >= 0);
const char* errorScopeName = kErrorScopeNames[errorState->fScopeIdx];
SKGPU_LOG_E("Failed in error scope (%s): %s", errorScopeName, msg);
errorState->fError |= kErrorScopeTypes[errorState->fScopeIdx];
}
errorState->fScopeIdx--;
errorState->fWait.signal();
};
// Pop all three error scopes:
// Internal
fDevice.PopErrorScope(errorCallback, &errorState);
errorState.fWait.busyWait();
errorState.fWait.reset();
// OutOfMemory
fDevice.PopErrorScope(errorCallback, &errorState);
errorState.fWait.busyWait();
errorState.fWait.reset();
// Validation
fDevice.PopErrorScope(errorCallback, &errorState);
errorState.fWait.busyWait();
fArmed = false;
return errorState.fError;
}
} // namespace skgpu::graphite