Allow internal errors for pipeline creation failure
Change-Id: I6b8c109ae67e230fea3fb14511c2b3562191c0fa
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/132300
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Loko Kung <lokokung@google.com>
diff --git a/src/dawn/native/Device.cpp b/src/dawn/native/Device.cpp
index 797773c..70007cf 100644
--- a/src/dawn/native/Device.cpp
+++ b/src/dawn/native/Device.cpp
@@ -1111,7 +1111,7 @@
utils::GetLabelForTrace(descriptor->label));
Ref<ComputePipelineBase> result;
- if (ConsumedError(CreateComputePipeline(descriptor), &result,
+ if (ConsumedError(CreateComputePipeline(descriptor), &result, InternalErrorType::Internal,
"calling %s.CreateComputePipeline(%s).", this, descriptor)) {
return ComputePipelineBase::MakeError(this, descriptor ? descriptor->label : nullptr);
}
@@ -1201,7 +1201,7 @@
utils::GetLabelForTrace(descriptor->label));
Ref<RenderPipelineBase> result;
- if (ConsumedError(CreateRenderPipeline(descriptor), &result,
+ if (ConsumedError(CreateRenderPipeline(descriptor), &result, InternalErrorType::Internal,
"calling %s.CreateRenderPipeline(%s).", this, descriptor)) {
return RenderPipelineBase::MakeError(this, descriptor ? descriptor->label : nullptr);
}
diff --git a/src/dawn/native/Error.cpp b/src/dawn/native/Error.cpp
index 40d9b2ad..d5e56f5 100644
--- a/src/dawn/native/Error.cpp
+++ b/src/dawn/native/Error.cpp
@@ -36,10 +36,8 @@
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:
+ return wgpu::ErrorType::Internal;
case InternalErrorType::DeviceLost:
return wgpu::ErrorType::DeviceLost;
diff --git a/src/dawn/tests/unittests/native/AllowedErrorTests.cpp b/src/dawn/tests/unittests/native/AllowedErrorTests.cpp
index 78b45d2..f140798 100644
--- a/src/dawn/tests/unittests/native/AllowedErrorTests.cpp
+++ b/src/dawn/tests/unittests/native/AllowedErrorTests.cpp
@@ -42,6 +42,7 @@
using ::testing::Test;
static constexpr char kOomErrorMessage[] = "Out of memory error";
+static constexpr char kInternalErrorMessage[] = "Internal error";
static constexpr std::string_view kComputeShader = R"(
@compute @workgroup_size(1) fn main() {}
@@ -237,6 +238,56 @@
device.CreateRenderPipeline(ToCppAPI(&desc));
}
+// Internal error from synchronously initializing a compute pipeline should not result in a device
+// loss.
+TEST_F(AllowedErrorTests, CreateComputePipelineInternalError) {
+ Ref<ShaderModuleMock> csModule = ShaderModuleMock::Create(mDeviceMock, kComputeShader.data());
+
+ ComputePipelineDescriptor desc = {};
+ desc.compute.module = csModule.Get();
+ desc.compute.entryPoint = "main";
+
+ Ref<ComputePipelineMock> computePipelineMock = ComputePipelineMock::Create(mDeviceMock, &desc);
+ EXPECT_CALL(*computePipelineMock.Get(), Initialize)
+ .WillOnce(Return(ByMove(DAWN_INTERNAL_ERROR(kInternalErrorMessage))));
+ EXPECT_CALL(*mDeviceMock, CreateUninitializedComputePipelineImpl)
+ .WillOnce(Return(ByMove(std::move(computePipelineMock))));
+
+ // Expect the internal error.
+ EXPECT_CALL(mDeviceErrorCb,
+ Call(WGPUErrorType_Internal, HasSubstr(kInternalErrorMessage), this))
+ .Times(1);
+ device.CreateComputePipeline(ToCppAPI(&desc));
+
+ // Device lost should only happen due to destruction.
+ EXPECT_CALL(mDeviceLostCb, Call(WGPUDeviceLostReason_Destroyed, _, this)).Times(1);
+}
+
+// Internal error from synchronously initializing a render pipeline should not result in a device
+// loss.
+TEST_F(AllowedErrorTests, CreateRenderPipelineInternalError) {
+ Ref<ShaderModuleMock> vsModule = ShaderModuleMock::Create(mDeviceMock, kVertexShader.data());
+
+ RenderPipelineDescriptor desc = {};
+ desc.vertex.module = vsModule.Get();
+ desc.vertex.entryPoint = "main";
+
+ Ref<RenderPipelineMock> renderPipelineMock = RenderPipelineMock::Create(mDeviceMock, &desc);
+ EXPECT_CALL(*renderPipelineMock.Get(), Initialize)
+ .WillOnce(Return(ByMove(DAWN_INTERNAL_ERROR(kInternalErrorMessage))));
+ EXPECT_CALL(*mDeviceMock, CreateUninitializedRenderPipelineImpl)
+ .WillOnce(Return(ByMove(std::move(renderPipelineMock))));
+
+ // Expect the internal error.
+ EXPECT_CALL(mDeviceErrorCb,
+ Call(WGPUErrorType_Internal, HasSubstr(kInternalErrorMessage), this))
+ .Times(1);
+ device.CreateRenderPipeline(ToCppAPI(&desc));
+
+ // Device lost should only happen due to destruction.
+ EXPECT_CALL(mDeviceLostCb, Call(WGPUDeviceLostReason_Destroyed, _, this)).Times(1);
+}
+
//
// Exercise async APIs where OOM errors do NOT currently cause a device lost.
//
@@ -293,6 +344,60 @@
EXPECT_CALL(mDeviceLostCb, Call(WGPUDeviceLostReason_Destroyed, _, this)).Times(1);
}
+// Internal error from asynchronously initializing a compute pipeline should not result in a device
+// loss.
+TEST_F(AllowedErrorTests, CreateComputePipelineAsyncInternalError) {
+ Ref<ShaderModuleMock> csModule = ShaderModuleMock::Create(mDeviceMock, kComputeShader.data());
+
+ ComputePipelineDescriptor desc = {};
+ desc.compute.module = csModule.Get();
+ desc.compute.entryPoint = "main";
+
+ Ref<ComputePipelineMock> computePipelineMock = ComputePipelineMock::Create(mDeviceMock, &desc);
+ EXPECT_CALL(*computePipelineMock.Get(), Initialize)
+ .WillOnce(Return(ByMove(DAWN_INTERNAL_ERROR(kInternalErrorMessage))));
+ EXPECT_CALL(*mDeviceMock, CreateUninitializedComputePipelineImpl)
+ .WillOnce(Return(ByMove(std::move(computePipelineMock))));
+
+ MockCallback<wgpu::CreateComputePipelineAsyncCallback> cb;
+ EXPECT_CALL(cb, Call(WGPUCreatePipelineAsyncStatus_InternalError, _,
+ HasSubstr(kInternalErrorMessage), this))
+ .Times(1);
+
+ device.CreateComputePipelineAsync(ToCppAPI(&desc), cb.Callback(), cb.MakeUserdata(this));
+ device.Tick();
+
+ // Device lost should only happen because of destruction.
+ EXPECT_CALL(mDeviceLostCb, Call(WGPUDeviceLostReason_Destroyed, _, this)).Times(1);
+}
+
+// Internal error from asynchronously initializing a render pipeline should not result in a device
+// loss.
+TEST_F(AllowedErrorTests, CreateRenderPipelineAsyncInternalError) {
+ Ref<ShaderModuleMock> vsModule = ShaderModuleMock::Create(mDeviceMock, kVertexShader.data());
+
+ RenderPipelineDescriptor desc = {};
+ desc.vertex.module = vsModule.Get();
+ desc.vertex.entryPoint = "main";
+
+ Ref<RenderPipelineMock> renderPipelineMock = RenderPipelineMock::Create(mDeviceMock, &desc);
+ EXPECT_CALL(*renderPipelineMock.Get(), Initialize)
+ .WillOnce(Return(ByMove(DAWN_INTERNAL_ERROR(kInternalErrorMessage))));
+ EXPECT_CALL(*mDeviceMock, CreateUninitializedRenderPipelineImpl)
+ .WillOnce(Return(ByMove(std::move(renderPipelineMock))));
+
+ MockCallback<wgpu::CreateRenderPipelineAsyncCallback> cb;
+ EXPECT_CALL(cb, Call(WGPUCreatePipelineAsyncStatus_InternalError, _,
+ HasSubstr(kInternalErrorMessage), this))
+ .Times(1);
+
+ device.CreateRenderPipelineAsync(ToCppAPI(&desc), cb.Callback(), cb.MakeUserdata(this));
+ device.Tick();
+
+ // Device lost should only happen because of destruction.
+ EXPECT_CALL(mDeviceLostCb, Call(WGPUDeviceLostReason_Destroyed, _, this)).Times(1);
+}
+
//
// Exercise APIs where OOM error are allowed and surfaced.
//