Separate device lost from internal errors.

The effect to the user is the same, the Dawn device gets lost. However
we need to make the difference internally because when the backend
device is lost we can clean up immediately. On the contrary on internal
errors, the backend device is still alive and processing commands so we
need to gracefully shut it down.

Bug: dawn:269

Change-Id: Ie13b33a4f9ac2e1f5f98b3723d83cf1c6205c988
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/17965
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
Corentin Wallez 2020-04-01 12:07:43 +00:00 committed by Commit Bot service account
parent 3da19b843f
commit a0afd31585
31 changed files with 157 additions and 78 deletions

View File

@ -32,7 +32,7 @@
{"value": 0, "name": "discrete GPU"}, {"value": 0, "name": "discrete GPU"},
{"value": 1, "name": "integrated GPU"}, {"value": 1, "name": "integrated GPU"},
{"value": 2, "name": "CPU"}, {"value": 2, "name": "CPU"},
{"value": 3, "name": "Unknown"} {"value": 3, "name": "unknown"}
] ]
}, },
"address mode": { "address mode": {

View File

@ -20,7 +20,7 @@ template<typename T>
MaybeError OpenGLFunctionsBase::LoadProc(GetProcAddress getProc, T* memberProc, const char* name) { MaybeError OpenGLFunctionsBase::LoadProc(GetProcAddress getProc, T* memberProc, const char* name) {
*memberProc = reinterpret_cast<T>(getProc(name)); *memberProc = reinterpret_cast<T>(getProc(name));
if (DAWN_UNLIKELY(memberProc == nullptr)) { if (DAWN_UNLIKELY(memberProc == nullptr)) {
return DAWN_DEVICE_LOST_ERROR(std::string("Couldn't load GL proc: ") + name); return DAWN_INTERNAL_ERROR(std::string("Couldn't load GL proc: ") + name);
} }
return {}; return {};
} }

View File

@ -109,23 +109,41 @@ namespace dawn_native {
mLossStatus = LossStatus::AlreadyLost; mLossStatus = LossStatus::AlreadyLost;
} }
void DeviceBase::HandleError(wgpu::ErrorType type, const char* message) { void DeviceBase::HandleError(InternalErrorType type, const char* message) {
if (type == wgpu::ErrorType::DeviceLost) { // 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) {
mLossStatus = LossStatus::BeingLost;
// Assert that errors are device loss so that we can continue with destruction.
AssertAndIgnoreDeviceLossError(WaitForIdleForDestruction());
HandleLoss(message); HandleLoss(message);
} }
// Still forward device loss to error scope so it can reject them all
mCurrentErrorScope->HandleError(type, message); // The device was lost for real, call the loss handler because all the backend objects are
// as if no longer in use.
if (type == InternalErrorType::DeviceLost) {
HandleLoss(message);
}
// Still forward device loss and internal errors to the error scopes so they all reject.
mCurrentErrorScope->HandleError(ToWGPUErrorType(type), message);
} }
void DeviceBase::InjectError(wgpu::ErrorType type, const char* message) { void DeviceBase::InjectError(wgpu::ErrorType type, const char* message) {
if (ConsumedError(ValidateErrorType(type))) { if (ConsumedError(ValidateErrorType(type))) {
return; return;
} }
if (DAWN_UNLIKELY(type == wgpu::ErrorType::NoError)) {
HandleError(wgpu::ErrorType::Validation, "Invalid injected error NoError"); // This method should only be used to make error scope reject. For DeviceLost there is the
// LoseForTesting function that can be used instead.
if (type != wgpu::ErrorType::Validation && type != wgpu::ErrorType::OutOfMemory) {
HandleError(InternalErrorType::Validation,
"Invalid injected error, must be Validation or OutOfMemory");
return; return;
} }
HandleError(type, message);
HandleError(FromWGPUErrorType(type), message);
} }
void DeviceBase::ConsumeError(std::unique_ptr<ErrorData> error) { void DeviceBase::ConsumeError(std::unique_ptr<ErrorData> error) {
@ -200,10 +218,7 @@ namespace dawn_native {
return; return;
} }
mLossStatus = LossStatus::BeingLost; HandleError(InternalErrorType::Internal, "Device lost for testing");
// Assert that errors are device loss so that we can continue with destruction
AssertAndIgnoreDeviceLossError(WaitForIdleForDestruction());
HandleError(wgpu::ErrorType::DeviceLost, "Device lost for testing");
} }
bool DeviceBase::IsLost() const { bool DeviceBase::IsLost() const {

View File

@ -44,7 +44,7 @@ namespace dawn_native {
DeviceBase(AdapterBase* adapter, const DeviceDescriptor* descriptor); DeviceBase(AdapterBase* adapter, const DeviceDescriptor* descriptor);
virtual ~DeviceBase(); virtual ~DeviceBase();
void HandleError(wgpu::ErrorType type, const char* message); void HandleError(InternalErrorType type, const char* message);
bool ConsumedError(MaybeError maybeError) { bool ConsumedError(MaybeError maybeError) {
if (DAWN_UNLIKELY(maybeError.IsError())) { if (DAWN_UNLIKELY(maybeError.IsError())) {

View File

@ -53,7 +53,7 @@ namespace dawn_native {
} }
} }
void EncodingContext::HandleError(wgpu::ErrorType type, const char* message) { void EncodingContext::HandleError(InternalErrorType type, const char* message) {
if (!IsFinished()) { if (!IsFinished()) {
// If the encoding context is not finished, errors are deferred until // If the encoding context is not finished, errors are deferred until
// Finish() is called. // Finish() is called.

View File

@ -39,7 +39,7 @@ namespace dawn_native {
CommandIterator* GetIterator(); CommandIterator* GetIterator();
// Functions to handle encoder errors // Functions to handle encoder errors
void HandleError(wgpu::ErrorType type, const char* message); void HandleError(InternalErrorType type, const char* message);
inline void ConsumeError(std::unique_ptr<ErrorData> error) { inline void ConsumeError(std::unique_ptr<ErrorData> error) {
HandleError(error->GetType(), error->GetMessage().c_str()); HandleError(error->GetType(), error->GetMessage().c_str());
@ -58,10 +58,10 @@ namespace dawn_native {
if (DAWN_UNLIKELY(encoder != mCurrentEncoder)) { if (DAWN_UNLIKELY(encoder != mCurrentEncoder)) {
if (mCurrentEncoder != mTopLevelEncoder) { if (mCurrentEncoder != mTopLevelEncoder) {
// The top level encoder was used when a pass encoder was current. // The top level encoder was used when a pass encoder was current.
HandleError(wgpu::ErrorType::Validation, HandleError(InternalErrorType::Validation,
"Command cannot be recorded inside a pass"); "Command cannot be recorded inside a pass");
} else { } else {
HandleError(wgpu::ErrorType::Validation, HandleError(InternalErrorType::Validation,
"Recording in an error or already ended pass encoder"); "Recording in an error or already ended pass encoder");
} }
return false; return false;

View File

@ -18,10 +18,43 @@
#include "dawn_native/dawn_platform.h" #include "dawn_native/dawn_platform.h"
namespace dawn_native { namespace dawn_native {
void AssertAndIgnoreDeviceLossError(MaybeError maybeError) { void AssertAndIgnoreDeviceLossError(MaybeError maybeError) {
if (maybeError.IsError()) { if (maybeError.IsError()) {
std::unique_ptr<ErrorData> errorData = maybeError.AcquireError(); std::unique_ptr<ErrorData> errorData = maybeError.AcquireError();
ASSERT(errorData->GetType() == wgpu::ErrorType::DeviceLost); ASSERT(errorData->GetType() == InternalErrorType::DeviceLost);
} }
} }
wgpu::ErrorType ToWGPUErrorType(InternalErrorType type) {
switch (type) {
case InternalErrorType::Validation:
return wgpu::ErrorType::Validation;
case InternalErrorType::OutOfMemory:
return wgpu::ErrorType::OutOfMemory;
// There is no equivalent of Internal errors in the WebGPU API. Internal errors cause
// the device at the API level to be lost, so treat it like a DeviceLost error.
case InternalErrorType::Internal:
case InternalErrorType::DeviceLost:
return wgpu::ErrorType::DeviceLost;
default:
return wgpu::ErrorType::Unknown;
}
}
InternalErrorType FromWGPUErrorType(wgpu::ErrorType type) {
switch (type) {
case wgpu::ErrorType::Validation:
return InternalErrorType::Validation;
case wgpu::ErrorType::OutOfMemory:
return InternalErrorType::OutOfMemory;
case wgpu::ErrorType::DeviceLost:
return InternalErrorType::DeviceLost;
default:
return InternalErrorType::Internal;
}
}
} // namespace dawn_native } // namespace dawn_native

View File

@ -22,7 +22,13 @@
namespace dawn_native { namespace dawn_native {
enum class InternalErrorType : uint32_t { Validation, DeviceLost, Unimplemented, OutOfMemory }; enum class InternalErrorType : uint32_t {
Validation,
DeviceLost,
Internal,
Unimplemented,
OutOfMemory
};
// MaybeError and ResultOrError are meant to be used as return value for function that are not // MaybeError and ResultOrError are meant to be used as return value for function that are not
// expected to, but might fail. The handling of error is potentially much slower than successes. // expected to, but might fail. The handling of error is potentially much slower than successes.
@ -40,11 +46,37 @@ namespace dawn_native {
// //
// but shorthand version for specific error types are preferred: // but shorthand version for specific error types are preferred:
// return DAWN_VALIDATION_ERROR("My error message"); // return DAWN_VALIDATION_ERROR("My error message");
//
// There are different types of errors that should be used for different purpose:
//
// - Validation: these are errors that show the user did something bad, which causes the
// whole call to be a no-op. It's most commonly found in the frontend but there can be some
// backend specific validation in non-conformant backends too.
//
// - Out of memory: creation of a Buffer or Texture failed because there isn't enough memory.
// This is similar to validation errors in that the call becomes a no-op and returns an
// error object, but is reported separated from validation to the user.
//
// - Device loss: the backend driver reported that the GPU has been lost, which means all
// previous commands magically disappeared and the only thing left to do is clean up.
// Note: Device loss should be used rarely and in most case you want to use Internal
// instead.
//
// - Internal: something happened that the backend didn't expect, and it doesn't know
// how to recover from that situation. This causes the device to be lost, but is separate
// from device loss, because the GPU execution is still happening so we need to clean up
// more gracefully.
//
// - Unimplemented: same as Internal except it puts "unimplemented" in the error message for
// more clarity.
#define DAWN_MAKE_ERROR(TYPE, MESSAGE) \ #define DAWN_MAKE_ERROR(TYPE, MESSAGE) \
::dawn_native::ErrorData::Create(TYPE, MESSAGE, __FILE__, __func__, __LINE__) ::dawn_native::ErrorData::Create(TYPE, MESSAGE, __FILE__, __func__, __LINE__)
#define DAWN_VALIDATION_ERROR(MESSAGE) DAWN_MAKE_ERROR(InternalErrorType::Validation, MESSAGE) #define DAWN_VALIDATION_ERROR(MESSAGE) DAWN_MAKE_ERROR(InternalErrorType::Validation, MESSAGE)
#define DAWN_DEVICE_LOST_ERROR(MESSAGE) DAWN_MAKE_ERROR(InternalErrorType::DeviceLost, MESSAGE) #define DAWN_DEVICE_LOST_ERROR(MESSAGE) DAWN_MAKE_ERROR(InternalErrorType::DeviceLost, MESSAGE)
#define DAWN_UNIMPLEMENTED_ERROR(MESSAGE) DAWN_MAKE_ERROR(InternalErrorType::Unimplemented, MESSAGE) #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)
#define DAWN_OUT_OF_MEMORY_ERROR(MESSAGE) DAWN_MAKE_ERROR(InternalErrorType::OutOfMemory, MESSAGE) #define DAWN_OUT_OF_MEMORY_ERROR(MESSAGE) DAWN_MAKE_ERROR(InternalErrorType::OutOfMemory, MESSAGE)
#define DAWN_CONCAT1(x, y) x##y #define DAWN_CONCAT1(x, y) x##y
@ -84,6 +116,9 @@ namespace dawn_native {
// Assert that errors are device loss so that we can continue with destruction // Assert that errors are device loss so that we can continue with destruction
void AssertAndIgnoreDeviceLossError(MaybeError maybeError); void AssertAndIgnoreDeviceLossError(MaybeError maybeError);
wgpu::ErrorType ToWGPUErrorType(InternalErrorType type);
InternalErrorType FromWGPUErrorType(wgpu::ErrorType type);
} // namespace dawn_native } // namespace dawn_native
#endif // DAWNNATIVE_ERROR_H_ #endif // DAWNNATIVE_ERROR_H_

View File

@ -42,23 +42,10 @@ namespace dawn_native {
mBacktrace.push_back(std::move(record)); mBacktrace.push_back(std::move(record));
} }
InternalErrorType ErrorData::GetInternalType() const { InternalErrorType ErrorData::GetType() const {
return mType; return mType;
} }
wgpu::ErrorType ErrorData::GetType() const {
switch (mType) {
case InternalErrorType::Validation:
return wgpu::ErrorType::Validation;
case InternalErrorType::OutOfMemory:
return wgpu::ErrorType::OutOfMemory;
case InternalErrorType::DeviceLost:
return wgpu::ErrorType::DeviceLost;
default:
return wgpu::ErrorType::Unknown;
}
}
const std::string& ErrorData::GetMessage() const { const std::string& ErrorData::GetMessage() const {
return mMessage; return mMessage;
} }

View File

@ -49,8 +49,7 @@ namespace dawn_native {
}; };
void AppendBacktrace(const char* file, const char* function, int line); void AppendBacktrace(const char* file, const char* function, int line);
InternalErrorType GetInternalType() const; InternalErrorType GetType() const;
wgpu::ErrorType GetType() const;
const std::string& GetMessage() const; const std::string& GetMessage() const;
const std::vector<BacktraceRecord>& GetBacktrace() const; const std::vector<BacktraceRecord>& GetBacktrace() const;

View File

@ -63,7 +63,7 @@ namespace dawn_native { namespace d3d12 {
const PlatformFunctions* functions = GetBackend()->GetFunctions(); const PlatformFunctions* functions = GetBackend()->GetFunctions();
if (FAILED(functions->d3d12CreateDevice(GetHardwareAdapter(), D3D_FEATURE_LEVEL_11_0, if (FAILED(functions->d3d12CreateDevice(GetHardwareAdapter(), D3D_FEATURE_LEVEL_11_0,
_uuidof(ID3D12Device), &mD3d12Device))) { _uuidof(ID3D12Device), &mD3d12Device))) {
return DAWN_DEVICE_LOST_ERROR("D3D12CreateDevice failed"); return DAWN_INTERNAL_ERROR("D3D12CreateDevice failed");
} }
DXGI_ADAPTER_DESC1 adapterDesc; DXGI_ADAPTER_DESC1 adapterDesc;

View File

@ -61,7 +61,7 @@ namespace dawn_native { namespace d3d12 {
} }
if (FAILED(functions->createDxgiFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&factory)))) { if (FAILED(functions->createDxgiFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&factory)))) {
return DAWN_DEVICE_LOST_ERROR("Failed to create a DXGI factory"); return DAWN_INTERNAL_ERROR("Failed to create a DXGI factory");
} }
ASSERT(factory != nullptr); ASSERT(factory != nullptr);

View File

@ -23,7 +23,7 @@ namespace dawn_native { namespace d3d12 {
} }
std::string message = std::string(context) + " failed with " + std::to_string(result); std::string message = std::string(context) + " failed with " + std::to_string(result);
return DAWN_DEVICE_LOST_ERROR(message); return DAWN_INTERNAL_ERROR(message);
} }
MaybeError CheckOutOfMemoryHRESULT(HRESULT result, const char* context) { MaybeError CheckOutOfMemoryHRESULT(HRESULT result, const char* context) {
@ -33,4 +33,4 @@ namespace dawn_native { namespace d3d12 {
return CheckHRESULT(result, context); return CheckHRESULT(result, context);
} }
}} // namespace dawn_native::d3d12 }} // namespace dawn_native::d3d12

View File

@ -45,7 +45,7 @@ namespace dawn_native { namespace d3d12 {
"D3D12SerializeVersionedRootSignature", &error) || "D3D12SerializeVersionedRootSignature", &error) ||
!mD3D12Lib.GetProc(&d3d12CreateVersionedRootSignatureDeserializer, !mD3D12Lib.GetProc(&d3d12CreateVersionedRootSignatureDeserializer,
"D3D12CreateVersionedRootSignatureDeserializer", &error)) { "D3D12CreateVersionedRootSignatureDeserializer", &error)) {
return DAWN_DEVICE_LOST_ERROR(error.c_str()); return DAWN_INTERNAL_ERROR(error.c_str());
} }
return {}; return {};
@ -55,7 +55,7 @@ namespace dawn_native { namespace d3d12 {
std::string error; std::string error;
if (!mD3D11Lib.Open("d3d11.dll", &error) || if (!mD3D11Lib.Open("d3d11.dll", &error) ||
!mD3D11Lib.GetProc(&d3d11on12CreateDevice, "D3D11On12CreateDevice", &error)) { !mD3D11Lib.GetProc(&d3d11on12CreateDevice, "D3D11On12CreateDevice", &error)) {
return DAWN_DEVICE_LOST_ERROR(error.c_str()); return DAWN_INTERNAL_ERROR(error.c_str());
} }
return {}; return {};
@ -66,7 +66,7 @@ namespace dawn_native { namespace d3d12 {
if (!mDXGILib.Open("dxgi.dll", &error) || if (!mDXGILib.Open("dxgi.dll", &error) ||
!mDXGILib.GetProc(&dxgiGetDebugInterface1, "DXGIGetDebugInterface1", &error) || !mDXGILib.GetProc(&dxgiGetDebugInterface1, "DXGIGetDebugInterface1", &error) ||
!mDXGILib.GetProc(&createDxgiFactory2, "CreateDXGIFactory2", &error)) { !mDXGILib.GetProc(&createDxgiFactory2, "CreateDXGIFactory2", &error)) {
return DAWN_DEVICE_LOST_ERROR(error.c_str()); return DAWN_INTERNAL_ERROR(error.c_str());
} }
return {}; return {};
@ -76,7 +76,7 @@ namespace dawn_native { namespace d3d12 {
std::string error; std::string error;
if (!mD3DCompilerLib.Open("d3dcompiler_47.dll", &error) || if (!mD3DCompilerLib.Open("d3dcompiler_47.dll", &error) ||
!mD3DCompilerLib.GetProc(&d3dCompile, "D3DCompile", &error)) { !mD3DCompilerLib.GetProc(&d3dCompile, "D3DCompile", &error)) {
return DAWN_DEVICE_LOST_ERROR(error.c_str()); return DAWN_INTERNAL_ERROR(error.c_str());
} }
return {}; return {};

View File

@ -40,7 +40,7 @@ namespace dawn_native { namespace d3d12 {
DawnSwapChainNextTexture next = {}; DawnSwapChainNextTexture next = {};
DawnSwapChainError error = im.GetNextTexture(im.userData, &next); DawnSwapChainError error = im.GetNextTexture(im.userData, &next);
if (error) { if (error) {
GetDevice()->HandleError(wgpu::ErrorType::Unknown, error); GetDevice()->HandleError(InternalErrorType::Internal, error);
return nullptr; return nullptr;
} }

View File

@ -57,7 +57,7 @@ namespace dawn_native { namespace metal {
} }
if (vendorId == 0) { if (vendorId == 0) {
return DAWN_DEVICE_LOST_ERROR("Failed to find vendor id with the device"); return DAWN_INTERNAL_ERROR("Failed to find vendor id with the device");
} }
// Set vendor id with 0 // Set vendor id with 0
@ -108,7 +108,7 @@ namespace dawn_native { namespace metal {
// Get a matching dictionary for the IOGraphicsAccelerator2 // Get a matching dictionary for the IOGraphicsAccelerator2
CFMutableDictionaryRef matchingDict = IORegistryEntryIDMatching([device registryID]); CFMutableDictionaryRef matchingDict = IORegistryEntryIDMatching([device registryID]);
if (matchingDict == nullptr) { if (matchingDict == nullptr) {
return DAWN_DEVICE_LOST_ERROR("Failed to create the matching dict for the device"); return DAWN_INTERNAL_ERROR("Failed to create the matching dict for the device");
} }
// IOServiceGetMatchingService will consume the reference on the matching dictionary, // IOServiceGetMatchingService will consume the reference on the matching dictionary,
@ -116,7 +116,7 @@ namespace dawn_native { namespace metal {
io_registry_entry_t acceleratorEntry = io_registry_entry_t acceleratorEntry =
IOServiceGetMatchingService(kIOMasterPortDefault, matchingDict); IOServiceGetMatchingService(kIOMasterPortDefault, matchingDict);
if (acceleratorEntry == IO_OBJECT_NULL) { if (acceleratorEntry == IO_OBJECT_NULL) {
return DAWN_DEVICE_LOST_ERROR( return DAWN_INTERNAL_ERROR(
"Failed to get the IO registry entry for the accelerator"); "Failed to get the IO registry entry for the accelerator");
} }
@ -125,7 +125,7 @@ namespace dawn_native { namespace metal {
if (IORegistryEntryGetParentEntry(acceleratorEntry, kIOServicePlane, &deviceEntry) != if (IORegistryEntryGetParentEntry(acceleratorEntry, kIOServicePlane, &deviceEntry) !=
kIOReturnSuccess) { kIOReturnSuccess) {
IOObjectRelease(acceleratorEntry); IOObjectRelease(acceleratorEntry);
return DAWN_DEVICE_LOST_ERROR("Failed to get the IO registry entry for the device"); return DAWN_INTERNAL_ERROR("Failed to get the IO registry entry for the device");
} }
ASSERT(deviceEntry != IO_OBJECT_NULL); ASSERT(deviceEntry != IO_OBJECT_NULL);

View File

@ -43,7 +43,7 @@ namespace dawn_native { namespace metal {
[mtlDevice newComputePipelineStateWithFunction:computeData.function error:&error]; [mtlDevice newComputePipelineStateWithFunction:computeData.function error:&error];
if (error != nil) { if (error != nil) {
NSLog(@" error => %@", error); NSLog(@" error => %@", error);
return DAWN_DEVICE_LOST_ERROR("Error creating pipeline state"); return DAWN_INTERNAL_ERROR("Error creating pipeline state");
} }
// Copy over the local workgroup size as it is passed to dispatch explicitly in Metal // Copy over the local workgroup size as it is passed to dispatch explicitly in Metal

View File

@ -391,7 +391,7 @@ namespace dawn_native { namespace metal {
[descriptorMTL release]; [descriptorMTL release];
if (error != nil) { if (error != nil) {
NSLog(@" error => %@", error); NSLog(@" error => %@", error);
return DAWN_DEVICE_LOST_ERROR("Error creating rendering pipeline state"); return DAWN_INTERNAL_ERROR("Error creating rendering pipeline state");
} }
} }

View File

@ -32,7 +32,7 @@ namespace dawn_native { namespace metal {
mMappedPointer = [mBuffer contents]; mMappedPointer = [mBuffer contents];
if (mMappedPointer == nullptr) { if (mMappedPointer == nullptr) {
return DAWN_DEVICE_LOST_ERROR("Unable to map staging buffer."); return DAWN_INTERNAL_ERROR("Unable to map staging buffer.");
} }
return {}; return {};

View File

@ -43,7 +43,7 @@ namespace dawn_native { namespace metal {
DawnSwapChainNextTexture next = {}; DawnSwapChainNextTexture next = {};
DawnSwapChainError error = im.GetNextTexture(im.userData, &next); DawnSwapChainError error = im.GetNextTexture(im.userData, &next);
if (error) { if (error) {
GetDevice()->HandleError(wgpu::ErrorType::Unknown, error); GetDevice()->HandleError(InternalErrorType::Internal, error);
return nullptr; return nullptr;
} }

View File

@ -211,7 +211,7 @@ namespace dawn_native { namespace null {
MaybeError Device::IncrementMemoryUsage(size_t bytes) { MaybeError Device::IncrementMemoryUsage(size_t bytes) {
static_assert(kMaxMemoryUsage <= std::numeric_limits<size_t>::max() / 2, ""); static_assert(kMaxMemoryUsage <= std::numeric_limits<size_t>::max() / 2, "");
if (bytes > kMaxMemoryUsage || mMemoryUsage + bytes > kMaxMemoryUsage) { if (bytes > kMaxMemoryUsage || mMemoryUsage + bytes > kMaxMemoryUsage) {
return DAWN_DEVICE_LOST_ERROR("Out of memory."); return DAWN_OUT_OF_MEMORY_ERROR("Out of memory.");
} }
mMemoryUsage += bytes; mMemoryUsage += bytes;
return {}; return {};

View File

@ -22,7 +22,7 @@ namespace dawn_native { namespace opengl {
MaybeError OpenGLFunctions::Initialize(GetProcAddress getProc) { MaybeError OpenGLFunctions::Initialize(GetProcAddress getProc) {
PFNGLGETSTRINGPROC getString = reinterpret_cast<PFNGLGETSTRINGPROC>(getProc("glGetString")); PFNGLGETSTRINGPROC getString = reinterpret_cast<PFNGLGETSTRINGPROC>(getProc("glGetString"));
if (getString == nullptr) { if (getString == nullptr) {
return DAWN_DEVICE_LOST_ERROR("Couldn't load glGetString"); return DAWN_INTERNAL_ERROR("Couldn't load glGetString");
} }
std::string version = reinterpret_cast<const char*>(getString(GL_VERSION)); std::string version = reinterpret_cast<const char*>(getString(GL_VERSION));

View File

@ -36,7 +36,7 @@ namespace dawn_native { namespace opengl {
DawnSwapChainNextTexture next = {}; DawnSwapChainNextTexture next = {};
DawnSwapChainError error = im.GetNextTexture(im.userData, &next); DawnSwapChainError error = im.GetNextTexture(im.userData, &next);
if (error) { if (error) {
GetDevice()->HandleError(wgpu::ErrorType::Unknown, error); GetDevice()->HandleError(InternalErrorType::Internal, error);
return nullptr; return nullptr;
} }
GLuint nativeTexture = next.texture.u32; GLuint nativeTexture = next.texture.u32;

View File

@ -40,7 +40,7 @@ namespace dawn_native { namespace vulkan {
MaybeError Adapter::Initialize() { MaybeError Adapter::Initialize() {
DAWN_TRY_ASSIGN(mDeviceInfo, GatherDeviceInfo(*this)); DAWN_TRY_ASSIGN(mDeviceInfo, GatherDeviceInfo(*this));
if (!mDeviceInfo.maintenance1) { if (!mDeviceInfo.maintenance1) {
return DAWN_DEVICE_LOST_ERROR( return DAWN_INTERNAL_ERROR(
"Dawn requires Vulkan 1.1 or Vulkan 1.0 with KHR_Maintenance1 in order to support " "Dawn requires Vulkan 1.1 or Vulkan 1.0 with KHR_Maintenance1 in order to support "
"viewport flipY"); "viewport flipY");
} }

View File

@ -86,7 +86,7 @@ namespace dawn_native { namespace vulkan {
if (GetInstance()->IsBackendValidationEnabled()) { if (GetInstance()->IsBackendValidationEnabled()) {
std::string vkDataDir = GetExecutableDirectory() + DAWN_VK_DATA_DIR; std::string vkDataDir = GetExecutableDirectory() + DAWN_VK_DATA_DIR;
if (!SetEnvironmentVar("VK_LAYER_PATH", vkDataDir.c_str())) { if (!SetEnvironmentVar("VK_LAYER_PATH", vkDataDir.c_str())) {
return DAWN_DEVICE_LOST_ERROR("Couldn't set VK_LAYER_PATH"); return DAWN_INTERNAL_ERROR("Couldn't set VK_LAYER_PATH");
} }
} }
#endif #endif
@ -94,7 +94,7 @@ namespace dawn_native { namespace vulkan {
std::string fullSwiftshaderICDPath = std::string fullSwiftshaderICDPath =
GetExecutableDirectory() + DAWN_SWIFTSHADER_VK_ICD_JSON; GetExecutableDirectory() + DAWN_SWIFTSHADER_VK_ICD_JSON;
if (!SetEnvironmentVar("VK_ICD_FILENAMES", fullSwiftshaderICDPath.c_str())) { if (!SetEnvironmentVar("VK_ICD_FILENAMES", fullSwiftshaderICDPath.c_str())) {
return DAWN_DEVICE_LOST_ERROR("Couldn't set VK_ICD_FILENAMES"); return DAWN_INTERNAL_ERROR("Couldn't set VK_ICD_FILENAMES");
} }
#endif #endif
@ -112,7 +112,7 @@ namespace dawn_native { namespace vulkan {
} }
#endif #endif
return DAWN_DEVICE_LOST_ERROR("Couldn't load Vulkan"); return DAWN_INTERNAL_ERROR("Couldn't load Vulkan");
} }
MaybeError Backend::Initialize() { MaybeError Backend::Initialize() {

View File

@ -385,7 +385,7 @@ namespace dawn_native { namespace vulkan {
} }
if (universalQueueFamily == -1) { if (universalQueueFamily == -1) {
return DAWN_DEVICE_LOST_ERROR("No universal queue family"); return DAWN_INTERNAL_ERROR("No universal queue family");
} }
mQueueFamily = static_cast<uint32_t>(universalQueueFamily); mQueueFamily = static_cast<uint32_t>(universalQueueFamily);
} }

View File

@ -52,7 +52,7 @@ namespace dawn_native { namespace vulkan {
mMappedPointer = mAllocation.GetMappedPointer(); mMappedPointer = mAllocation.GetMappedPointer();
if (mMappedPointer == nullptr) { if (mMappedPointer == nullptr) {
return DAWN_DEVICE_LOST_ERROR("Unable to map staging buffer."); return DAWN_INTERNAL_ERROR("Unable to map staging buffer.");
} }
return {}; return {};

View File

@ -43,7 +43,7 @@ namespace dawn_native { namespace vulkan {
DawnSwapChainError error = im.GetNextTexture(im.userData, &next); DawnSwapChainError error = im.GetNextTexture(im.userData, &next);
if (error) { if (error) {
GetDevice()->HandleError(wgpu::ErrorType::Unknown, error); GetDevice()->HandleError(InternalErrorType::Internal, error);
return nullptr; return nullptr;
} }

View File

@ -73,8 +73,14 @@ namespace dawn_native { namespace vulkan {
if (DAWN_LIKELY(result == VK_SUCCESS)) { if (DAWN_LIKELY(result == VK_SUCCESS)) {
return {}; return {};
} }
std::string message = std::string(context) + " failed with " + VkResultAsString(result); std::string message = std::string(context) + " failed with " + VkResultAsString(result);
return DAWN_DEVICE_LOST_ERROR(message);
if (result == VK_ERROR_DEVICE_LOST) {
return DAWN_DEVICE_LOST_ERROR(message);
} else {
return DAWN_INTERNAL_ERROR(message);
}
} }
MaybeError CheckVkOOMThenSuccessImpl(VkResult result, const char* context) { MaybeError CheckVkOOMThenSuccessImpl(VkResult result, const char* context) {
@ -83,10 +89,14 @@ namespace dawn_native { namespace vulkan {
} }
std::string message = std::string(context) + " failed with " + VkResultAsString(result); std::string message = std::string(context) + " failed with " + VkResultAsString(result);
if (result == VK_ERROR_OUT_OF_DEVICE_MEMORY || result == VK_FAKE_DEVICE_OOM_FOR_TESTING) { if (result == VK_ERROR_OUT_OF_DEVICE_MEMORY || result == VK_FAKE_DEVICE_OOM_FOR_TESTING) {
return DAWN_OUT_OF_MEMORY_ERROR(message); return DAWN_OUT_OF_MEMORY_ERROR(message);
} else if (result == VK_ERROR_DEVICE_LOST) {
return DAWN_DEVICE_LOST_ERROR(message);
} else {
return DAWN_INTERNAL_ERROR(message);
} }
return DAWN_DEVICE_LOST_ERROR(message);
} }
}} // namespace dawn_native::vulkan }} // namespace dawn_native::vulkan

View File

@ -22,12 +22,12 @@ namespace dawn_native { namespace vulkan {
#define GET_GLOBAL_PROC(name) \ #define GET_GLOBAL_PROC(name) \
name = reinterpret_cast<decltype(name)>(GetInstanceProcAddr(nullptr, "vk" #name)); \ name = reinterpret_cast<decltype(name)>(GetInstanceProcAddr(nullptr, "vk" #name)); \
if (name == nullptr) { \ if (name == nullptr) { \
return DAWN_DEVICE_LOST_ERROR(std::string("Couldn't get proc vk") + #name); \ return DAWN_INTERNAL_ERROR(std::string("Couldn't get proc vk") + #name); \
} }
MaybeError VulkanFunctions::LoadGlobalProcs(const DynamicLib& vulkanLib) { MaybeError VulkanFunctions::LoadGlobalProcs(const DynamicLib& vulkanLib) {
if (!vulkanLib.GetProc(&GetInstanceProcAddr, "vkGetInstanceProcAddr")) { if (!vulkanLib.GetProc(&GetInstanceProcAddr, "vkGetInstanceProcAddr")) {
return DAWN_DEVICE_LOST_ERROR("Couldn't get vkGetInstanceProcAddr"); return DAWN_INTERNAL_ERROR("Couldn't get vkGetInstanceProcAddr");
} }
GET_GLOBAL_PROC(CreateInstance); GET_GLOBAL_PROC(CreateInstance);
@ -44,7 +44,7 @@ namespace dawn_native { namespace vulkan {
#define GET_INSTANCE_PROC_BASE(name, procName) \ #define GET_INSTANCE_PROC_BASE(name, procName) \
name = reinterpret_cast<decltype(name)>(GetInstanceProcAddr(instance, "vk" #procName)); \ name = reinterpret_cast<decltype(name)>(GetInstanceProcAddr(instance, "vk" #procName)); \
if (name == nullptr) { \ if (name == nullptr) { \
return DAWN_DEVICE_LOST_ERROR(std::string("Couldn't get proc vk") + #procName); \ return DAWN_INTERNAL_ERROR(std::string("Couldn't get proc vk") + #procName); \
} }
#define GET_INSTANCE_PROC(name) GET_INSTANCE_PROC_BASE(name, name) #define GET_INSTANCE_PROC(name) GET_INSTANCE_PROC_BASE(name, name)
@ -147,7 +147,7 @@ namespace dawn_native { namespace vulkan {
#define GET_DEVICE_PROC(name) \ #define GET_DEVICE_PROC(name) \
name = reinterpret_cast<decltype(name)>(GetDeviceProcAddr(device, "vk" #name)); \ name = reinterpret_cast<decltype(name)>(GetDeviceProcAddr(device, "vk" #name)); \
if (name == nullptr) { \ if (name == nullptr) { \
return DAWN_DEVICE_LOST_ERROR(std::string("Couldn't get proc vk") + #name); \ return DAWN_INTERNAL_ERROR(std::string("Couldn't get proc vk") + #name); \
} }
MaybeError VulkanFunctions::LoadDeviceProcs(VkDevice device, MaybeError VulkanFunctions::LoadDeviceProcs(VkDevice device,

View File

@ -93,7 +93,7 @@ namespace dawn_native { namespace vulkan {
// incomplete otherwise. This means that both values represent a success. // incomplete otherwise. This means that both values represent a success.
// This is the same for all Enumarte functions // This is the same for all Enumarte functions
if (result != VK_SUCCESS && result != VK_INCOMPLETE) { if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
return DAWN_DEVICE_LOST_ERROR("vkEnumerateInstanceLayerProperties"); return DAWN_INTERNAL_ERROR("vkEnumerateInstanceLayerProperties");
} }
info.layers.resize(count); info.layers.resize(count);
@ -123,7 +123,7 @@ namespace dawn_native { namespace vulkan {
// Gather the info about the instance extensions // Gather the info about the instance extensions
{ {
if (!EnumerateInstanceExtensions(nullptr, vkFunctions, &info.extensions)) { if (!EnumerateInstanceExtensions(nullptr, vkFunctions, &info.extensions)) {
return DAWN_DEVICE_LOST_ERROR("vkEnumerateInstanceExtensionProperties"); return DAWN_INTERNAL_ERROR("vkEnumerateInstanceExtensionProperties");
} }
for (const auto& extension : info.extensions) { for (const auto& extension : info.extensions) {
@ -169,7 +169,7 @@ namespace dawn_native { namespace vulkan {
std::vector<VkExtensionProperties> layer_extensions; std::vector<VkExtensionProperties> layer_extensions;
if (!EnumerateInstanceExtensions(kLayerNameFuchsiaImagePipeSwapchain, vkFunctions, if (!EnumerateInstanceExtensions(kLayerNameFuchsiaImagePipeSwapchain, vkFunctions,
&layer_extensions)) { &layer_extensions)) {
return DAWN_DEVICE_LOST_ERROR("vkEnumerateInstanceExtensionProperties"); return DAWN_INTERNAL_ERROR("vkEnumerateInstanceExtensionProperties");
} }
for (const auto& extension : layer_extensions) { for (const auto& extension : layer_extensions) {
@ -207,7 +207,7 @@ namespace dawn_native { namespace vulkan {
VkResult result = VkResult result =
VkResult::WrapUnsafe(vkFunctions.EnumeratePhysicalDevices(instance, &count, nullptr)); VkResult::WrapUnsafe(vkFunctions.EnumeratePhysicalDevices(instance, &count, nullptr));
if (result != VK_SUCCESS && result != VK_INCOMPLETE) { if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
return DAWN_DEVICE_LOST_ERROR("vkEnumeratePhysicalDevices"); return DAWN_INTERNAL_ERROR("vkEnumeratePhysicalDevices");
} }
std::vector<VkPhysicalDevice> physicalDevices(count); std::vector<VkPhysicalDevice> physicalDevices(count);
@ -254,7 +254,7 @@ namespace dawn_native { namespace vulkan {
VkResult result = VkResult::WrapUnsafe( VkResult result = VkResult::WrapUnsafe(
vkFunctions.EnumerateDeviceLayerProperties(physicalDevice, &count, nullptr)); vkFunctions.EnumerateDeviceLayerProperties(physicalDevice, &count, nullptr));
if (result != VK_SUCCESS && result != VK_INCOMPLETE) { if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
return DAWN_DEVICE_LOST_ERROR("vkEnumerateDeviceLayerProperties"); return DAWN_INTERNAL_ERROR("vkEnumerateDeviceLayerProperties");
} }
info.layers.resize(count); info.layers.resize(count);
@ -269,7 +269,7 @@ namespace dawn_native { namespace vulkan {
VkResult result = VkResult::WrapUnsafe(vkFunctions.EnumerateDeviceExtensionProperties( VkResult result = VkResult::WrapUnsafe(vkFunctions.EnumerateDeviceExtensionProperties(
physicalDevice, nullptr, &count, nullptr)); physicalDevice, nullptr, &count, nullptr));
if (result != VK_SUCCESS && result != VK_INCOMPLETE) { if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
return DAWN_DEVICE_LOST_ERROR("vkEnumerateDeviceExtensionProperties"); return DAWN_INTERNAL_ERROR("vkEnumerateDeviceExtensionProperties");
} }
info.extensions.resize(count); info.extensions.resize(count);
@ -357,7 +357,7 @@ namespace dawn_native { namespace vulkan {
VkResult result = VkResult::WrapUnsafe(vkFunctions.GetPhysicalDeviceSurfaceFormatsKHR( VkResult result = VkResult::WrapUnsafe(vkFunctions.GetPhysicalDeviceSurfaceFormatsKHR(
physicalDevice, surface, &count, nullptr)); physicalDevice, surface, &count, nullptr));
if (result != VK_SUCCESS && result != VK_INCOMPLETE) { if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
return DAWN_DEVICE_LOST_ERROR("vkGetPhysicalDeviceSurfaceFormatsKHR"); return DAWN_INTERNAL_ERROR("vkGetPhysicalDeviceSurfaceFormatsKHR");
} }
info.formats.resize(count); info.formats.resize(count);
@ -373,7 +373,7 @@ namespace dawn_native { namespace vulkan {
VkResult::WrapUnsafe(vkFunctions.GetPhysicalDeviceSurfacePresentModesKHR( VkResult::WrapUnsafe(vkFunctions.GetPhysicalDeviceSurfacePresentModesKHR(
physicalDevice, surface, &count, nullptr)); physicalDevice, surface, &count, nullptr));
if (result != VK_SUCCESS && result != VK_INCOMPLETE) { if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
return DAWN_DEVICE_LOST_ERROR("vkGetPhysicalDeviceSurfacePresentModesKHR"); return DAWN_INTERNAL_ERROR("vkGetPhysicalDeviceSurfacePresentModesKHR");
} }
info.presentModes.resize(count); info.presentModes.resize(count);