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>
This commit is contained in:
parent
a8236a5529
commit
e241d64d25
|
@ -1111,7 +1111,7 @@ ComputePipelineBase* DeviceBase::APICreateComputePipeline(
|
||||||
utils::GetLabelForTrace(descriptor->label));
|
utils::GetLabelForTrace(descriptor->label));
|
||||||
|
|
||||||
Ref<ComputePipelineBase> result;
|
Ref<ComputePipelineBase> result;
|
||||||
if (ConsumedError(CreateComputePipeline(descriptor), &result,
|
if (ConsumedError(CreateComputePipeline(descriptor), &result, InternalErrorType::Internal,
|
||||||
"calling %s.CreateComputePipeline(%s).", this, descriptor)) {
|
"calling %s.CreateComputePipeline(%s).", this, descriptor)) {
|
||||||
return ComputePipelineBase::MakeError(this, descriptor ? descriptor->label : nullptr);
|
return ComputePipelineBase::MakeError(this, descriptor ? descriptor->label : nullptr);
|
||||||
}
|
}
|
||||||
|
@ -1201,7 +1201,7 @@ RenderPipelineBase* DeviceBase::APICreateRenderPipeline(
|
||||||
utils::GetLabelForTrace(descriptor->label));
|
utils::GetLabelForTrace(descriptor->label));
|
||||||
|
|
||||||
Ref<RenderPipelineBase> result;
|
Ref<RenderPipelineBase> result;
|
||||||
if (ConsumedError(CreateRenderPipeline(descriptor), &result,
|
if (ConsumedError(CreateRenderPipeline(descriptor), &result, InternalErrorType::Internal,
|
||||||
"calling %s.CreateRenderPipeline(%s).", this, descriptor)) {
|
"calling %s.CreateRenderPipeline(%s).", this, descriptor)) {
|
||||||
return RenderPipelineBase::MakeError(this, descriptor ? descriptor->label : nullptr);
|
return RenderPipelineBase::MakeError(this, descriptor ? descriptor->label : nullptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,10 +36,8 @@ wgpu::ErrorType ToWGPUErrorType(InternalErrorType type) {
|
||||||
return wgpu::ErrorType::Validation;
|
return wgpu::ErrorType::Validation;
|
||||||
case InternalErrorType::OutOfMemory:
|
case InternalErrorType::OutOfMemory:
|
||||||
return wgpu::ErrorType::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::Internal:
|
||||||
|
return wgpu::ErrorType::Internal;
|
||||||
case InternalErrorType::DeviceLost:
|
case InternalErrorType::DeviceLost:
|
||||||
return wgpu::ErrorType::DeviceLost;
|
return wgpu::ErrorType::DeviceLost;
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ using ::testing::StrictMock;
|
||||||
using ::testing::Test;
|
using ::testing::Test;
|
||||||
|
|
||||||
static constexpr char kOomErrorMessage[] = "Out of memory error";
|
static constexpr char kOomErrorMessage[] = "Out of memory error";
|
||||||
|
static constexpr char kInternalErrorMessage[] = "Internal error";
|
||||||
|
|
||||||
static constexpr std::string_view kComputeShader = R"(
|
static constexpr std::string_view kComputeShader = R"(
|
||||||
@compute @workgroup_size(1) fn main() {}
|
@compute @workgroup_size(1) fn main() {}
|
||||||
|
@ -237,6 +238,56 @@ TEST_F(AllowedErrorTests, CreateRenderPipeline) {
|
||||||
device.CreateRenderPipeline(ToCppAPI(&desc));
|
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.
|
// Exercise async APIs where OOM errors do NOT currently cause a device lost.
|
||||||
//
|
//
|
||||||
|
@ -293,6 +344,60 @@ TEST_F(AllowedErrorTests, CreateRenderPipelineAsync) {
|
||||||
EXPECT_CALL(mDeviceLostCb, Call(WGPUDeviceLostReason_Destroyed, _, this)).Times(1);
|
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.
|
// Exercise APIs where OOM error are allowed and surfaced.
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in New Issue