Support ErrorScopes for asynchronous GPU execution

This changes updates ErrorScopes so that scopes enclosing a
Queue::Submit or Queue::Signal resolve their callbacks asynchronously
after GPU execution is complete.

Bug: dawn:153
Change-Id: I0e0b8a9f19f3f29d1b6a3683938154b87f190a07
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/10701
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
This commit is contained in:
Austin Eng
2019-09-17 18:24:07 +00:00
committed by Commit Bot service account
parent bb3c895619
commit be990077f4
9 changed files with 190 additions and 6 deletions

View File

@@ -132,3 +132,68 @@ TEST_F(ErrorScopeValidationTest, PushPopBalanced) {
EXPECT_FALSE(device.PopErrorScope(ToMockDevicePopErrorScopeCallback, this + 2));
}
}
// Test that error scopes do not call their callbacks until after an enclosed Queue::Submit
// completes
TEST_F(ErrorScopeValidationTest, CallbackAfterQueueSubmit) {
dawn::Queue queue = device.CreateQueue();
device.PushErrorScope(dawn::ErrorFilter::OutOfMemory);
queue.Submit(0, nullptr);
device.PopErrorScope(ToMockDevicePopErrorScopeCallback, this);
EXPECT_CALL(*mockDevicePopErrorScopeCallback, Call(DAWN_ERROR_TYPE_NO_ERROR, _, this)).Times(1);
// Side effects of Queue::Submit only are seen after Tick()
device.Tick();
}
// Test that parent error scopes do not call their callbacks until after an enclosed Queue::Submit
// completes
TEST_F(ErrorScopeValidationTest, CallbackAfterQueueSubmitNested) {
dawn::Queue queue = device.CreateQueue();
device.PushErrorScope(dawn::ErrorFilter::OutOfMemory);
device.PushErrorScope(dawn::ErrorFilter::OutOfMemory);
queue.Submit(0, nullptr);
device.PopErrorScope(ToMockDevicePopErrorScopeCallback, this);
device.PopErrorScope(ToMockDevicePopErrorScopeCallback, this + 1);
EXPECT_CALL(*mockDevicePopErrorScopeCallback, Call(DAWN_ERROR_TYPE_NO_ERROR, _, this)).Times(1);
EXPECT_CALL(*mockDevicePopErrorScopeCallback, Call(DAWN_ERROR_TYPE_NO_ERROR, _, this + 1))
.Times(1);
// Side effects of Queue::Submit only are seen after Tick()
device.Tick();
}
// Test a callback that returns asynchronously followed by a synchronous one
TEST_F(ErrorScopeValidationTest, AsynchronousThenSynchronous) {
dawn::Queue queue = device.CreateQueue();
device.PushErrorScope(dawn::ErrorFilter::OutOfMemory);
queue.Submit(0, nullptr);
device.PopErrorScope(ToMockDevicePopErrorScopeCallback, this);
EXPECT_CALL(*mockDevicePopErrorScopeCallback, Call(DAWN_ERROR_TYPE_NO_ERROR, _, this + 1))
.Times(1);
device.PushErrorScope(dawn::ErrorFilter::OutOfMemory);
device.PopErrorScope(ToMockDevicePopErrorScopeCallback, this + 1);
EXPECT_CALL(*mockDevicePopErrorScopeCallback, Call(DAWN_ERROR_TYPE_NO_ERROR, _, this)).Times(1);
// Side effects of Queue::Submit only are seen after Tick()
device.Tick();
}
// Test that if the device is destroyed before the callback occurs, it is called with UNKNOWN.
TEST_F(ErrorScopeValidationTest, DeviceDestroyedBeforeCallback) {
dawn::Queue queue = device.CreateQueue();
device.PushErrorScope(dawn::ErrorFilter::OutOfMemory);
queue.Submit(0, nullptr);
device.PopErrorScope(ToMockDevicePopErrorScopeCallback, this);
EXPECT_CALL(*mockDevicePopErrorScopeCallback, Call(DAWN_ERROR_TYPE_UNKNOWN, _, this)).Times(1);
device = nullptr;
}