Immediately call fence and map callbacks on device loss.
This is more in line with what happens in dawn_wire and Blink's WebGPU implementation. It also allows fixing the Fence-related DeviceLost tests to destroy the mock fence callback on destruction, which in turns fixes a crash on dawn_end2end_tests exit on MSVC x64 debug. Bug: dawn:602 Change-Id: I277e7fa284a573854ed46576602d5f6819db1357 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/38526 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Auto-Submit: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
2df77f4325
commit
c1d3a66bd2
|
@ -35,7 +35,10 @@ namespace dawn_native {
|
||||||
: buffer(std::move(buffer)), id(id) {
|
: buffer(std::move(buffer)), id(id) {
|
||||||
}
|
}
|
||||||
void Finish() override {
|
void Finish() override {
|
||||||
buffer->OnMapRequestCompleted(id);
|
buffer->OnMapRequestCompleted(id, WGPUBufferMapAsyncStatus_Success);
|
||||||
|
}
|
||||||
|
void HandleDeviceLoss() override {
|
||||||
|
buffer->OnMapRequestCompleted(id, WGPUBufferMapAsyncStatus_DeviceLost);
|
||||||
}
|
}
|
||||||
~MapRequestTask() override = default;
|
~MapRequestTask() override = default;
|
||||||
|
|
||||||
|
@ -537,8 +540,8 @@ namespace dawn_native {
|
||||||
mState = BufferState::Destroyed;
|
mState = BufferState::Destroyed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferBase::OnMapRequestCompleted(MapRequestID mapID) {
|
void BufferBase::OnMapRequestCompleted(MapRequestID mapID, WGPUBufferMapAsyncStatus status) {
|
||||||
CallMapCallback(mapID, WGPUBufferMapAsyncStatus_Success);
|
CallMapCallback(mapID, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BufferBase::IsDataInitialized() const {
|
bool BufferBase::IsDataInitialized() const {
|
||||||
|
|
|
@ -53,7 +53,7 @@ namespace dawn_native {
|
||||||
wgpu::BufferUsage GetUsage() const;
|
wgpu::BufferUsage GetUsage() const;
|
||||||
|
|
||||||
MaybeError MapAtCreation();
|
MaybeError MapAtCreation();
|
||||||
void OnMapRequestCompleted(MapRequestID mapID);
|
void OnMapRequestCompleted(MapRequestID mapID, WGPUBufferMapAsyncStatus status);
|
||||||
|
|
||||||
MaybeError ValidateCanUseOnQueueNow() const;
|
MaybeError ValidateCanUseOnQueueNow() const;
|
||||||
|
|
||||||
|
|
|
@ -240,6 +240,8 @@ namespace dawn_native {
|
||||||
|
|
||||||
// The device was lost, call the application callback.
|
// The device was lost, call the application callback.
|
||||||
if (type == InternalErrorType::DeviceLost && mDeviceLostCallback != nullptr) {
|
if (type == InternalErrorType::DeviceLost && mDeviceLostCallback != nullptr) {
|
||||||
|
mDefaultQueue->HandleDeviceLoss();
|
||||||
|
|
||||||
mDeviceLostCallback(message, mDeviceLostUserdata);
|
mDeviceLostCallback(message, mDeviceLostUserdata);
|
||||||
mDeviceLostCallback = nullptr;
|
mDeviceLostCallback = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,10 @@ namespace dawn_native {
|
||||||
: fence(std::move(fence)), value(value) {
|
: fence(std::move(fence)), value(value) {
|
||||||
}
|
}
|
||||||
void Finish() override {
|
void Finish() override {
|
||||||
fence->SetCompletedValue(value);
|
fence->SetCompletedValue(value, WGPUFenceCompletionStatus_Success);
|
||||||
|
}
|
||||||
|
void HandleDeviceLoss() override {
|
||||||
|
fence->SetCompletedValue(value, WGPUFenceCompletionStatus_DeviceLost);
|
||||||
}
|
}
|
||||||
~FenceInFlight() override = default;
|
~FenceInFlight() override = default;
|
||||||
|
|
||||||
|
@ -116,18 +119,14 @@ namespace dawn_native {
|
||||||
mSignalValue = signalValue;
|
mSignalValue = signalValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fence::SetCompletedValue(FenceAPISerial completedValue) {
|
void Fence::SetCompletedValue(FenceAPISerial completedValue, WGPUFenceCompletionStatus status) {
|
||||||
ASSERT(!IsError());
|
ASSERT(!IsError());
|
||||||
ASSERT(completedValue <= mSignalValue);
|
ASSERT(completedValue <= mSignalValue);
|
||||||
ASSERT(completedValue > mCompletedValue);
|
ASSERT(completedValue > mCompletedValue);
|
||||||
mCompletedValue = completedValue;
|
mCompletedValue = completedValue;
|
||||||
|
|
||||||
for (auto& request : mRequests.IterateUpTo(mCompletedValue)) {
|
for (auto& request : mRequests.IterateUpTo(mCompletedValue)) {
|
||||||
if (GetDevice()->IsLost()) {
|
request.completionCallback(status, request.userdata);
|
||||||
request.completionCallback(WGPUFenceCompletionStatus_DeviceLost, request.userdata);
|
|
||||||
} else {
|
|
||||||
request.completionCallback(WGPUFenceCompletionStatus_Success, request.userdata);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mRequests.ClearUpTo(mCompletedValue);
|
mRequests.ClearUpTo(mCompletedValue);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ namespace dawn_native {
|
||||||
friend class QueueBase;
|
friend class QueueBase;
|
||||||
friend struct FenceInFlight;
|
friend struct FenceInFlight;
|
||||||
void SetSignaledValue(FenceAPISerial signalValue);
|
void SetSignaledValue(FenceAPISerial signalValue);
|
||||||
void SetCompletedValue(FenceAPISerial completedValue);
|
void SetCompletedValue(FenceAPISerial completedValue, WGPUFenceCompletionStatus status);
|
||||||
void UpdateFenceOnComplete(Fence* fence, FenceAPISerial value);
|
void UpdateFenceOnComplete(Fence* fence, FenceAPISerial value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -192,6 +192,13 @@ namespace dawn_native {
|
||||||
mTasksInFlight.ClearUpTo(finishedSerial);
|
mTasksInFlight.ClearUpTo(finishedSerial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QueueBase::HandleDeviceLoss() {
|
||||||
|
for (auto& task : mTasksInFlight.IterateAll()) {
|
||||||
|
task->HandleDeviceLoss();
|
||||||
|
}
|
||||||
|
mTasksInFlight.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
Fence* QueueBase::CreateFence(const FenceDescriptor* descriptor) {
|
Fence* QueueBase::CreateFence(const FenceDescriptor* descriptor) {
|
||||||
if (GetDevice()->ConsumedError(ValidateCreateFence(descriptor))) {
|
if (GetDevice()->ConsumedError(ValidateCreateFence(descriptor))) {
|
||||||
return Fence::MakeError(GetDevice());
|
return Fence::MakeError(GetDevice());
|
||||||
|
|
|
@ -30,6 +30,7 @@ namespace dawn_native {
|
||||||
struct TaskInFlight {
|
struct TaskInFlight {
|
||||||
virtual ~TaskInFlight();
|
virtual ~TaskInFlight();
|
||||||
virtual void Finish() = 0;
|
virtual void Finish() = 0;
|
||||||
|
virtual void HandleDeviceLoss() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
static QueueBase* MakeError(DeviceBase* device);
|
static QueueBase* MakeError(DeviceBase* device);
|
||||||
|
@ -52,6 +53,7 @@ namespace dawn_native {
|
||||||
|
|
||||||
void TrackTask(std::unique_ptr<TaskInFlight> task, ExecutionSerial serial);
|
void TrackTask(std::unique_ptr<TaskInFlight> task, ExecutionSerial serial);
|
||||||
void Tick(ExecutionSerial finishedSerial);
|
void Tick(ExecutionSerial finishedSerial);
|
||||||
|
void HandleDeviceLoss();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QueueBase(DeviceBase* device);
|
QueueBase(DeviceBase* device);
|
||||||
|
|
|
@ -65,6 +65,7 @@ class DeviceLostTest : public DawnTest {
|
||||||
|
|
||||||
void TearDown() override {
|
void TearDown() override {
|
||||||
mockDeviceLostCallback = nullptr;
|
mockDeviceLostCallback = nullptr;
|
||||||
|
mockFenceOnCompletionCallback = nullptr;
|
||||||
DawnTest::TearDown();
|
DawnTest::TearDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,8 +450,8 @@ TEST_P(DeviceLostTest, FenceOnCompletionFails) {
|
||||||
ASSERT_DEVICE_ERROR(fence.OnCompletion(2u, ToMockFenceOnCompletionFails, nullptr));
|
ASSERT_DEVICE_ERROR(fence.OnCompletion(2u, ToMockFenceOnCompletionFails, nullptr));
|
||||||
ASSERT_DEVICE_ERROR(device.Tick());
|
ASSERT_DEVICE_ERROR(device.Tick());
|
||||||
|
|
||||||
// completed value should not have changed from initial value
|
// completed value is the last value signaled (all previous GPU operations are as if completed)
|
||||||
EXPECT_EQ(fence.GetCompletedValue(), 0u);
|
EXPECT_EQ(fence.GetCompletedValue(), 2u);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that Fence::OnCompletion callbacks with device lost status when device is lost after calling
|
// Test that Fence::OnCompletion callbacks with device lost status when device is lost after calling
|
||||||
|
@ -469,7 +470,7 @@ TEST_P(DeviceLostTest, FenceOnCompletionBeforeLossFails) {
|
||||||
SetCallbackAndLoseForTesting();
|
SetCallbackAndLoseForTesting();
|
||||||
ASSERT_DEVICE_ERROR(device.Tick());
|
ASSERT_DEVICE_ERROR(device.Tick());
|
||||||
|
|
||||||
EXPECT_EQ(fence.GetCompletedValue(), 0u);
|
EXPECT_EQ(fence.GetCompletedValue(), 2u);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regression test for the Null backend not properly setting the completedSerial when
|
// Regression test for the Null backend not properly setting the completedSerial when
|
||||||
|
|
Loading…
Reference in New Issue