Make ConsumedError require handling the returned bool.
This change makes it harder to misuse ConsumedError which can cause device loss. When it is a known error, instead use HandleError to bypass the "unlikely" if clause. Bug: dawn:1336 Change-Id: I3052db343fe4080b257f1c2f9535f743a0e78526 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/120384 Reviewed-by: Austin Eng <enga@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Loko Kung <lokokung@google.com> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
e11208e9ce
commit
d81aca7106
|
@ -506,9 +506,7 @@ void BufferBase::APIUnmap() {
|
|||
if (GetDevice()->ConsumedError(ValidateUnmap(), "calling %s.Unmap().", this)) {
|
||||
return;
|
||||
}
|
||||
if (GetDevice()->ConsumedError(Unmap(), "calling %s.Unmap().", this)) {
|
||||
return;
|
||||
}
|
||||
DAWN_UNUSED(GetDevice()->ConsumedError(Unmap(), "calling %s.Unmap().", this));
|
||||
}
|
||||
|
||||
MaybeError BufferBase::Unmap() {
|
||||
|
|
|
@ -151,7 +151,7 @@ ObjectType ComputePassEncoder::GetType() const {
|
|||
|
||||
void ComputePassEncoder::APIEnd() {
|
||||
if (mEnded && IsValidationEnabled()) {
|
||||
GetDevice()->ConsumedError(DAWN_VALIDATION_ERROR("%s was already ended.", this));
|
||||
GetDevice()->HandleError(DAWN_VALIDATION_ERROR("%s was already ended.", this));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -469,6 +469,7 @@ void DeviceBase::APIDestroy() {
|
|||
void DeviceBase::HandleError(std::unique_ptr<ErrorData> error,
|
||||
InternalErrorType additionalAllowedErrors,
|
||||
WGPUDeviceLostReason lost_reason) {
|
||||
AppendDebugLayerMessages(error.get());
|
||||
InternalErrorType allowedErrors =
|
||||
InternalErrorType::Validation | InternalErrorType::DeviceLost | additionalAllowedErrors;
|
||||
InternalErrorType type = error->GetType();
|
||||
|
@ -545,7 +546,6 @@ void DeviceBase::HandleError(std::unique_ptr<ErrorData> error,
|
|||
void DeviceBase::ConsumeError(std::unique_ptr<ErrorData> error,
|
||||
InternalErrorType additionalAllowedErrors) {
|
||||
ASSERT(error != nullptr);
|
||||
AppendDebugLayerMessages(error.get());
|
||||
HandleError(std::move(error), additionalAllowedErrors);
|
||||
}
|
||||
|
||||
|
@ -1203,21 +1203,24 @@ BufferBase* DeviceBase::APICreateErrorBuffer(const BufferDescriptor* desc) {
|
|||
// The validation errors on BufferDescriptor should be prior to any OOM errors when
|
||||
// MapppedAtCreation == false.
|
||||
MaybeError maybeError = ValidateBufferDescriptor(this, &fakeDescriptor);
|
||||
if (maybeError.IsError()) {
|
||||
ConsumedError(maybeError.AcquireError(), InternalErrorType::OutOfMemory,
|
||||
"calling %s.CreateBuffer(%s).", this, desc);
|
||||
} else {
|
||||
const DawnBufferDescriptorErrorInfoFromWireClient* clientErrorInfo = nullptr;
|
||||
FindInChain(desc->nextInChain, &clientErrorInfo);
|
||||
if (clientErrorInfo != nullptr && clientErrorInfo->outOfMemory) {
|
||||
ConsumedError(DAWN_OUT_OF_MEMORY_ERROR("Failed to allocate memory for buffer mapping"),
|
||||
InternalErrorType::OutOfMemory);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the size of the error buffer to 0 as this function is called only when an OOM happens at
|
||||
// the client side.
|
||||
fakeDescriptor.size = 0;
|
||||
|
||||
if (maybeError.IsError()) {
|
||||
std::unique_ptr<ErrorData> error = maybeError.AcquireError();
|
||||
error->AppendContext("calling %s.CreateBuffer(%s).", this, desc);
|
||||
HandleError(std::move(error), InternalErrorType::OutOfMemory);
|
||||
} else {
|
||||
const DawnBufferDescriptorErrorInfoFromWireClient* clientErrorInfo = nullptr;
|
||||
FindInChain(desc->nextInChain, &clientErrorInfo);
|
||||
if (clientErrorInfo != nullptr && clientErrorInfo->outOfMemory) {
|
||||
HandleError(DAWN_OUT_OF_MEMORY_ERROR("Failed to allocate memory for buffer mapping"),
|
||||
InternalErrorType::OutOfMemory);
|
||||
}
|
||||
}
|
||||
|
||||
return BufferBase::MakeError(this, &fakeDescriptor);
|
||||
}
|
||||
|
||||
|
@ -1401,7 +1404,7 @@ void DeviceBase::APIInjectError(wgpu::ErrorType type, const char* message) {
|
|||
}
|
||||
|
||||
void DeviceBase::APIValidateTextureDescriptor(const TextureDescriptor* desc) {
|
||||
ConsumedError(ValidateTextureDescriptor(this, desc));
|
||||
DAWN_UNUSED(ConsumedError(ValidateTextureDescriptor(this, desc)));
|
||||
}
|
||||
|
||||
QueueBase* DeviceBase::GetQueue() const {
|
||||
|
|
|
@ -76,8 +76,12 @@ class DeviceBase : public RefCountedWithExternalCount {
|
|||
InternalErrorType additionalAllowedErrors = InternalErrorType::None,
|
||||
WGPUDeviceLostReason lost_reason = WGPUDeviceLostReason_Undefined);
|
||||
|
||||
bool ConsumedError(MaybeError maybeError,
|
||||
InternalErrorType additionalAllowedErrors = InternalErrorType::None) {
|
||||
// Variants of ConsumedError must use the returned boolean to handle failure cases since an
|
||||
// error may cause a device loss and further execution may be undefined. This is especially
|
||||
// true for the ResultOrError variants.
|
||||
[[nodiscard]] bool ConsumedError(
|
||||
MaybeError maybeError,
|
||||
InternalErrorType additionalAllowedErrors = InternalErrorType::None) {
|
||||
if (DAWN_UNLIKELY(maybeError.IsError())) {
|
||||
ConsumeError(maybeError.AcquireError(), additionalAllowedErrors);
|
||||
return true;
|
||||
|
@ -86,9 +90,10 @@ class DeviceBase : public RefCountedWithExternalCount {
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
bool ConsumedError(ResultOrError<T> resultOrError,
|
||||
T* result,
|
||||
InternalErrorType additionalAllowedErrors = InternalErrorType::None) {
|
||||
[[nodiscard]] bool ConsumedError(
|
||||
ResultOrError<T> resultOrError,
|
||||
T* result,
|
||||
InternalErrorType additionalAllowedErrors = InternalErrorType::None) {
|
||||
if (DAWN_UNLIKELY(resultOrError.IsError())) {
|
||||
ConsumeError(resultOrError.AcquireError(), additionalAllowedErrors);
|
||||
return true;
|
||||
|
@ -98,10 +103,10 @@ class DeviceBase : public RefCountedWithExternalCount {
|
|||
}
|
||||
|
||||
template <typename... Args>
|
||||
bool ConsumedError(MaybeError maybeError,
|
||||
InternalErrorType additionalAllowedErrors,
|
||||
const char* formatStr,
|
||||
const Args&... args) {
|
||||
[[nodiscard]] bool ConsumedError(MaybeError maybeError,
|
||||
InternalErrorType additionalAllowedErrors,
|
||||
const char* formatStr,
|
||||
const Args&... args) {
|
||||
if (DAWN_UNLIKELY(maybeError.IsError())) {
|
||||
std::unique_ptr<ErrorData> error = maybeError.AcquireError();
|
||||
if (error->GetType() == InternalErrorType::Validation) {
|
||||
|
@ -114,17 +119,18 @@ class DeviceBase : public RefCountedWithExternalCount {
|
|||
}
|
||||
|
||||
template <typename... Args>
|
||||
bool ConsumedError(MaybeError maybeError, const char* formatStr, Args&&... args) {
|
||||
return ConsumedError(std::move(maybeError), InternalErrorType::None, formatStr,
|
||||
std::forward<Args>(args)...);
|
||||
[[nodiscard]] bool ConsumedError(MaybeError maybeError,
|
||||
const char* formatStr,
|
||||
const Args&... args) {
|
||||
return ConsumedError(std::move(maybeError), InternalErrorType::None, formatStr, args...);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
bool ConsumedError(ResultOrError<T> resultOrError,
|
||||
T* result,
|
||||
InternalErrorType additionalAllowedErrors,
|
||||
const char* formatStr,
|
||||
const Args&... args) {
|
||||
[[nodiscard]] bool ConsumedError(ResultOrError<T> resultOrError,
|
||||
T* result,
|
||||
InternalErrorType additionalAllowedErrors,
|
||||
const char* formatStr,
|
||||
const Args&... args) {
|
||||
if (DAWN_UNLIKELY(resultOrError.IsError())) {
|
||||
std::unique_ptr<ErrorData> error = resultOrError.AcquireError();
|
||||
if (error->GetType() == InternalErrorType::Validation) {
|
||||
|
@ -138,12 +144,12 @@ class DeviceBase : public RefCountedWithExternalCount {
|
|||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
bool ConsumedError(ResultOrError<T> resultOrError,
|
||||
T* result,
|
||||
const char* formatStr,
|
||||
Args&&... args) {
|
||||
[[nodiscard]] bool ConsumedError(ResultOrError<T> resultOrError,
|
||||
T* result,
|
||||
const char* formatStr,
|
||||
const Args&... args) {
|
||||
return ConsumedError(std::move(resultOrError), result, InternalErrorType::None, formatStr,
|
||||
std::forward<Args>(args)...);
|
||||
args...);
|
||||
}
|
||||
|
||||
MaybeError ValidateObject(const ApiObjectBase* object) const;
|
||||
|
|
|
@ -281,7 +281,7 @@ void QueueBase::APIWriteBuffer(BufferBase* buffer,
|
|||
uint64_t bufferOffset,
|
||||
const void* data,
|
||||
size_t size) {
|
||||
GetDevice()->ConsumedError(WriteBuffer(buffer, bufferOffset, data, size));
|
||||
DAWN_UNUSED(GetDevice()->ConsumedError(WriteBuffer(buffer, bufferOffset, data, size)));
|
||||
}
|
||||
|
||||
MaybeError QueueBase::WriteBuffer(BufferBase* buffer,
|
||||
|
@ -322,8 +322,8 @@ void QueueBase::APIWriteTexture(const ImageCopyTexture* destination,
|
|||
size_t dataSize,
|
||||
const TextureDataLayout* dataLayout,
|
||||
const Extent3D* writeSize) {
|
||||
GetDevice()->ConsumedError(
|
||||
WriteTextureInternal(destination, data, dataSize, *dataLayout, writeSize));
|
||||
DAWN_UNUSED(GetDevice()->ConsumedError(
|
||||
WriteTextureInternal(destination, data, dataSize, *dataLayout, writeSize)));
|
||||
}
|
||||
|
||||
MaybeError QueueBase::WriteTextureInternal(const ImageCopyTexture* destination,
|
||||
|
@ -389,16 +389,16 @@ void QueueBase::APICopyTextureForBrowser(const ImageCopyTexture* source,
|
|||
const ImageCopyTexture* destination,
|
||||
const Extent3D* copySize,
|
||||
const CopyTextureForBrowserOptions* options) {
|
||||
GetDevice()->ConsumedError(
|
||||
CopyTextureForBrowserInternal(source, destination, copySize, options));
|
||||
DAWN_UNUSED(GetDevice()->ConsumedError(
|
||||
CopyTextureForBrowserInternal(source, destination, copySize, options)));
|
||||
}
|
||||
|
||||
void QueueBase::APICopyExternalTextureForBrowser(const ImageCopyExternalTexture* source,
|
||||
const ImageCopyTexture* destination,
|
||||
const Extent3D* copySize,
|
||||
const CopyTextureForBrowserOptions* options) {
|
||||
GetDevice()->ConsumedError(
|
||||
CopyExternalTextureForBrowserInternal(source, destination, copySize, options));
|
||||
DAWN_UNUSED(GetDevice()->ConsumedError(
|
||||
CopyExternalTextureForBrowserInternal(source, destination, copySize, options)));
|
||||
}
|
||||
|
||||
MaybeError QueueBase::CopyTextureForBrowserInternal(const ImageCopyTexture* source,
|
||||
|
|
|
@ -137,7 +137,7 @@ void RenderPassEncoder::TrackQueryAvailability(QuerySetBase* querySet, uint32_t
|
|||
|
||||
void RenderPassEncoder::APIEnd() {
|
||||
if (mEnded && IsValidationEnabled()) {
|
||||
GetDevice()->ConsumedError(DAWN_VALIDATION_ERROR("%s was already ended.", this));
|
||||
GetDevice()->HandleError(DAWN_VALIDATION_ERROR("%s was already ended.", this));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,16 +35,16 @@ class ErrorSwapChain final : public SwapChainBase {
|
|||
wgpu::TextureUsage allowedUsage,
|
||||
uint32_t width,
|
||||
uint32_t height) override {
|
||||
GetDevice()->ConsumedError(DAWN_VALIDATION_ERROR("%s is an error swapchain.", this));
|
||||
GetDevice()->HandleError(DAWN_VALIDATION_ERROR("%s is an error swapchain.", this));
|
||||
}
|
||||
|
||||
TextureViewBase* APIGetCurrentTextureView() override {
|
||||
GetDevice()->ConsumedError(DAWN_VALIDATION_ERROR("%s is an error swapchain.", this));
|
||||
GetDevice()->HandleError(DAWN_VALIDATION_ERROR("%s is an error swapchain.", this));
|
||||
return TextureViewBase::MakeError(GetDevice());
|
||||
}
|
||||
|
||||
void APIPresent() override {
|
||||
GetDevice()->ConsumedError(DAWN_VALIDATION_ERROR("%s is an error swapchain.", this));
|
||||
GetDevice()->HandleError(DAWN_VALIDATION_ERROR("%s is an error swapchain.", this));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -300,7 +300,7 @@ void NewSwapChainBase::APIConfigure(wgpu::TextureFormat format,
|
|||
wgpu::TextureUsage allowedUsage,
|
||||
uint32_t width,
|
||||
uint32_t height) {
|
||||
GetDevice()->ConsumedError(
|
||||
GetDevice()->HandleError(
|
||||
DAWN_VALIDATION_ERROR("Configure is invalid for surface-based swapchains."));
|
||||
}
|
||||
|
||||
|
|
|
@ -226,6 +226,6 @@ TEST_F(DeviceTickValidationTest, DestroyDeviceBeforeInternalTick) {
|
|||
ExpectDeviceDestruction();
|
||||
device.Destroy();
|
||||
dawn::native::DeviceBase* nativeDevice = dawn::native::FromAPI(device.Get());
|
||||
ASSERT_DEVICE_ERROR(nativeDevice->ConsumedError(nativeDevice->Tick()),
|
||||
ASSERT_DEVICE_ERROR(EXPECT_TRUE(nativeDevice->ConsumedError(nativeDevice->Tick())),
|
||||
HasSubstr("[Device] is lost."));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue