[dawn][tests] Updates operation waiting in general.
- Track last process event commands in the native EventManager to
more accurately return whether there are further pending events
after a ProcessEvent call.
- Removes extraneous ProcessEventCmd in wire client since the
wire automatically includes that call now anyways.
- Adds a couple of additional entry points in wire related testing
utils to allow for clearer operation waiting.
- Updates test fixture waiting helpers to utilize new helpers so
that we can wait until all operations are complete including
re-entrant callbacks.
Change-Id: Iaddb815bda4bf236bb770169c5b2c8d36967e474
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/190981
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Loko Kung <lokokung@google.com>
diff --git a/src/dawn/native/EventManager.cpp b/src/dawn/native/EventManager.cpp
index 7f49ee3..55dcf76 100644
--- a/src/dawn/native/EventManager.cpp
+++ b/src/dawn/native/EventManager.cpp
@@ -376,6 +376,13 @@
if (!events->has_value()) {
return;
}
+ if (event->mCallbackMode != wgpu::CallbackMode::WaitAnyOnly) {
+ FutureID lastProcessedEventID = mLastProcessEventID.load(std::memory_order_acquire);
+ while (lastProcessedEventID < futureID &&
+ !mLastProcessEventID.compare_exchange_weak(lastProcessedEventID, futureID,
+ std::memory_order_acq_rel)) {
+ }
+ }
(*events)->emplace(futureID, std::move(event));
});
return futureID;
@@ -462,13 +469,16 @@
return readyEnd != futures.end();
});
- // Finally, call callbacks.
+ // Finally, call callbacks while comparing the last process event id with any new ones that may
+ // have been created via the callbacks.
+ FutureID lastProcessEventID = mLastProcessEventID.load(std::memory_order_acquire);
for (auto& event : completable) {
event->EnsureComplete(EventCompletionType::Ready);
}
// Note that in the event of all progressing events completing, but there exists non-progressing
// events, we will return true one extra time.
- return hasIncompleteEvents && hasProgressingEvents;
+ return hasIncompleteEvents && hasProgressingEvents &&
+ (lastProcessEventID != mLastProcessEventID.load(std::memory_order_acquire));
}
wgpu::WaitStatus EventManager::WaitAny(size_t count, FutureWaitInfo* infos, Nanoseconds timeout) {
diff --git a/src/dawn/native/EventManager.h b/src/dawn/native/EventManager.h
index 3f23374..0946708 100644
--- a/src/dawn/native/EventManager.h
+++ b/src/dawn/native/EventManager.h
@@ -88,13 +88,14 @@
size_t mTimedWaitAnyMaxCount = kTimedWaitAnyMaxCountDefault;
std::atomic<FutureID> mNextFutureID = 1;
- // Only 1 thread is allowed to call ProcessEvents at a time. This lock ensures that.
- std::mutex mProcessEventLock;
-
// Freed once the user has dropped their last ref to the Instance, so can't call WaitAny or
// ProcessEvents anymore. This breaks reference cycles.
using EventMap = absl::flat_hash_map<FutureID, Ref<TrackedEvent>>;
MutexProtected<std::optional<EventMap>> mEvents;
+
+ // Records last process event id in order to properly return whether or not there are still
+ // events to process when we have re-entrant callbacks.
+ std::atomic<FutureID> mLastProcessEventID = 0;
};
struct QueueAndSerial {
diff --git a/src/dawn/tests/DawnTest.cpp b/src/dawn/tests/DawnTest.cpp
index 55885b4..e6fdcbd 100644
--- a/src/dawn/tests/DawnTest.cpp
+++ b/src/dawn/tests/DawnTest.cpp
@@ -803,6 +803,10 @@
queue = nullptr;
device = nullptr;
adapter = nullptr;
+
+ // Since the native instance is a global, we can't rely on it's destruction to clean up all
+ // callbacks. Instead, for each test, we make sure to clear all events.
+ WaitForAllOperations();
instance = nullptr;
// Since the native instance is a global, we can't rely on it's destruction to clean up all
@@ -1666,17 +1670,29 @@
}
void DawnTestBase::WaitForAllOperations() {
- // Callback might be invoked on another thread that calls the same WaitABit() method, not
- // necessarily the current thread. So we need to use atomic here.
- std::atomic<bool> done(false);
- device.GetQueue().OnSubmittedWorkDone(
- [](WGPUQueueWorkDoneStatus, void* userdata) {
- *static_cast<std::atomic<bool>*>(userdata) = true;
- },
- &done);
- while (!done.load()) {
- WaitABit();
+ // TODO: crbug.com/42241461 - This block should be removed once we have migrated all tests to
+ // use the new entry points.
+ if (device != nullptr) {
+ // Callback might be invoked on another thread that calls the same WaitABit() method, not
+ // necessarily the current thread. So we need to use atomic here.
+ std::atomic<bool> done(false);
+ device.GetQueue().OnSubmittedWorkDone(
+ [](WGPUQueueWorkDoneStatus, void* userdata) {
+ *static_cast<std::atomic<bool>*>(userdata) = true;
+ },
+ &done);
+ while (!done.load()) {
+ WaitABit();
+ }
}
+
+ do {
+ FlushWire();
+ if (UsesWire() && instance != nullptr) {
+ instance.ProcessEvents();
+ }
+ } while (dawn::native::InstanceProcessEvents(gTestEnv->GetInstance()->Get()) ||
+ !mWireHelper->IsIdle());
}
DawnTestBase::ReadbackReservation DawnTestBase::ReserveReadback(wgpu::Device targetDevice,
diff --git a/src/dawn/tests/unittests/validation/BufferValidationTests.cpp b/src/dawn/tests/unittests/validation/BufferValidationTests.cpp
index f858e1d..d1b520f 100644
--- a/src/dawn/tests/unittests/validation/BufferValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/BufferValidationTests.cpp
@@ -191,7 +191,7 @@
buf.MapAsync(wgpu::MapMode::Read, 0, 4, ToMockBufferMapAsyncCallback, nullptr);
EXPECT_CALL(*mockBufferMapAsyncCallback, Call(WGPUBufferMapAsyncStatus_Success, _)).Times(1);
- WaitForAllOperations(device);
+ WaitForAllOperations();
buf.Unmap();
}
@@ -203,7 +203,7 @@
buf.MapAsync(wgpu::MapMode::Write, 0, 4, ToMockBufferMapAsyncCallback, nullptr);
EXPECT_CALL(*mockBufferMapAsyncCallback, Call(WGPUBufferMapAsyncStatus_Success, _)).Times(1);
- WaitForAllOperations(device);
+ WaitForAllOperations();
buf.Unmap();
}
@@ -331,7 +331,7 @@
{
wgpu::Buffer buffer = CreateMapReadBuffer(4);
buffer.MapAsync(wgpu::MapMode::Read, 0, 4, nullptr, nullptr);
- WaitForAllOperations(device);
+ WaitForAllOperations();
AssertMapAsyncError(buffer, wgpu::MapMode::Read, 0, 4);
}
{
@@ -341,7 +341,7 @@
{
wgpu::Buffer buffer = CreateMapWriteBuffer(4);
buffer.MapAsync(wgpu::MapMode::Write, 0, 4, nullptr, nullptr);
- WaitForAllOperations(device);
+ WaitForAllOperations();
AssertMapAsyncError(buffer, wgpu::MapMode::Write, 0, 4);
}
{
@@ -363,7 +363,7 @@
buffer.MapAsync(wgpu::MapMode::Read, 0, 4, ToMockBufferMapAsyncCallback, this + 1);
EXPECT_CALL(*mockBufferMapAsyncCallback, Call(WGPUBufferMapAsyncStatus_Success, this))
.Times(1);
- WaitForAllOperations(device);
+ WaitForAllOperations();
}
// Read + non-overlapping range
@@ -377,7 +377,7 @@
buffer.MapAsync(wgpu::MapMode::Read, 8, 8, ToMockBufferMapAsyncCallback, this + 1);
EXPECT_CALL(*mockBufferMapAsyncCallback, Call(WGPUBufferMapAsyncStatus_Success, this))
.Times(1);
- WaitForAllOperations(device);
+ WaitForAllOperations();
}
// Write + overlapping range
@@ -391,7 +391,7 @@
buffer.MapAsync(wgpu::MapMode::Write, 0, 4, ToMockBufferMapAsyncCallback, this + 1);
EXPECT_CALL(*mockBufferMapAsyncCallback, Call(WGPUBufferMapAsyncStatus_Success, this))
.Times(1);
- WaitForAllOperations(device);
+ WaitForAllOperations();
}
// Write + non-overlapping range
@@ -405,7 +405,7 @@
buffer.MapAsync(wgpu::MapMode::Write, 8, 8, ToMockBufferMapAsyncCallback, this + 1);
EXPECT_CALL(*mockBufferMapAsyncCallback, Call(WGPUBufferMapAsyncStatus_Success, this))
.Times(1);
- WaitForAllOperations(device);
+ WaitForAllOperations();
}
}
@@ -435,7 +435,7 @@
buf.Unmap();
// The callback shouldn't be called again.
- WaitForAllOperations(device);
+ WaitForAllOperations();
}
{
wgpu::Buffer buf = CreateMapWriteBuffer(4);
@@ -447,7 +447,7 @@
buf.Unmap();
// The callback shouldn't be called again.
- WaitForAllOperations(device);
+ WaitForAllOperations();
}
}
@@ -466,7 +466,7 @@
buf.MapAsync(wgpu::MapMode::Read, 8, 8, ToMockBufferMapAsyncCallback, this + 1);
EXPECT_CALL(*mockBufferMapAsyncCallback, Call(WGPUBufferMapAsyncStatus_Success, this + 1))
.Times(1);
- WaitForAllOperations(device);
+ WaitForAllOperations();
// Check that only the second MapAsync had an effect
ASSERT_EQ(nullptr, buf.GetConstMappedRange(0));
@@ -484,7 +484,7 @@
buf.MapAsync(wgpu::MapMode::Write, 8, 8, ToMockBufferMapAsyncCallback, this + 1);
EXPECT_CALL(*mockBufferMapAsyncCallback, Call(WGPUBufferMapAsyncStatus_Success, this + 1))
.Times(1);
- WaitForAllOperations(device);
+ WaitForAllOperations();
// Check that only the second MapAsync had an effect
ASSERT_EQ(nullptr, buf.GetConstMappedRange(0));
@@ -504,7 +504,7 @@
buf.Destroy();
// The callback shouldn't be called again.
- WaitForAllOperations(device);
+ WaitForAllOperations();
}
{
wgpu::Buffer buf = CreateMapWriteBuffer(4);
@@ -516,7 +516,7 @@
buf.Destroy();
// The callback shouldn't be called again.
- WaitForAllOperations(device);
+ WaitForAllOperations();
}
}
@@ -529,7 +529,7 @@
EXPECT_CALL(*mockBufferMapAsyncCallback, Call(WGPUBufferMapAsyncStatus_Success, _))
.WillOnce(InvokeWithoutArgs([&] { buf.Unmap(); }));
- WaitForAllOperations(device);
+ WaitForAllOperations();
}
{
wgpu::Buffer buf = CreateMapWriteBuffer(4);
@@ -538,7 +538,7 @@
EXPECT_CALL(*mockBufferMapAsyncCallback, Call(WGPUBufferMapAsyncStatus_Success, _))
.WillOnce(InvokeWithoutArgs([&] { buf.Unmap(); }));
- WaitForAllOperations(device);
+ WaitForAllOperations();
}
}
@@ -551,7 +551,7 @@
EXPECT_CALL(*mockBufferMapAsyncCallback, Call(WGPUBufferMapAsyncStatus_Success, _))
.WillOnce(InvokeWithoutArgs([&] { buf.Destroy(); }));
- WaitForAllOperations(device);
+ WaitForAllOperations();
}
{
wgpu::Buffer buf = CreateMapWriteBuffer(4);
@@ -560,7 +560,7 @@
EXPECT_CALL(*mockBufferMapAsyncCallback, Call(WGPUBufferMapAsyncStatus_Success, _))
.WillOnce(InvokeWithoutArgs([&] { buf.Destroy(); }));
- WaitForAllOperations(device);
+ WaitForAllOperations();
}
}
@@ -582,9 +582,9 @@
}));
buf.MapAsync(wgpu::MapMode::Read, 0, 4, ToMockBufferMapAsyncCallback, nullptr);
- WaitForAllOperations(device);
+ WaitForAllOperations();
// we need another wire flush to make the MapAsync in the callback to the server
- WaitForAllOperations(device);
+ WaitForAllOperations();
}
}
@@ -605,9 +605,9 @@
ASSERT_DEVICE_ERROR(
buf.MapAsync(wgpu::MapMode::Write, 0, 4, ToMockBufferMapAsyncCallback, nullptr));
- WaitForAllOperations(device);
+ WaitForAllOperations();
// we need another wire flush to make the MapAsync in the callback to the server
- WaitForAllOperations(device);
+ WaitForAllOperations();
}
// Test MapAsync call in MapAsync Unmapped before callback callback
@@ -624,8 +624,8 @@
buf.MapAsync(wgpu::MapMode::Read, 0, 4, ToMockBufferMapAsyncCallback, nullptr);
buf.Unmap();
- WaitForAllOperations(device);
- WaitForAllOperations(device);
+ WaitForAllOperations();
+ WaitForAllOperations();
}
// Test MapAsync call in MapAsync Destroyed before callback callback
@@ -644,8 +644,8 @@
buf.MapAsync(wgpu::MapMode::Read, 0, 4, ToMockBufferMapAsyncCallback, nullptr);
buf.Destroy();
- WaitForAllOperations(device);
- WaitForAllOperations(device);
+ WaitForAllOperations();
+ WaitForAllOperations();
}
}
@@ -732,7 +732,7 @@
EXPECT_EQ(WGPUBufferMapAsyncStatus_ValidationError, status);
},
nullptr));
- WaitForAllOperations(device);
+ WaitForAllOperations();
}
// Test that it is valid to submit a buffer in a queue with a map usage if it is unmapped
@@ -773,7 +773,7 @@
encoder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
wgpu::CommandBuffer commands = encoder.Finish();
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
- WaitForAllOperations(device);
+ WaitForAllOperations();
}
{
wgpu::Buffer bufA = device.CreateBuffer(&descriptorA);
@@ -785,7 +785,7 @@
encoder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
wgpu::CommandBuffer commands = encoder.Finish();
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
- WaitForAllOperations(device);
+ WaitForAllOperations();
}
{
wgpu::BufferDescriptor mappedBufferDesc = descriptorA;
@@ -797,7 +797,7 @@
encoder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
wgpu::CommandBuffer commands = encoder.Finish();
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
- WaitForAllOperations(device);
+ WaitForAllOperations();
}
{
wgpu::BufferDescriptor mappedBufferDesc = descriptorB;
@@ -809,7 +809,7 @@
encoder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
wgpu::CommandBuffer commands = encoder.Finish();
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
- WaitForAllOperations(device);
+ WaitForAllOperations();
}
}
@@ -894,7 +894,7 @@
buf.MapAsync(wgpu::MapMode::Read, 0, 4, ToMockBufferMapAsyncCallback, nullptr);
EXPECT_CALL(*mockBufferMapAsyncCallback, Call(WGPUBufferMapAsyncStatus_Success, _))
.Times(1);
- WaitForAllOperations(device);
+ WaitForAllOperations();
buf.Unmap();
ASSERT_EQ(nullptr, buf.GetMappedRange());
@@ -907,7 +907,7 @@
buf.MapAsync(wgpu::MapMode::Write, 0, 4, ToMockBufferMapAsyncCallback, nullptr);
EXPECT_CALL(*mockBufferMapAsyncCallback, Call(WGPUBufferMapAsyncStatus_Success, _))
.Times(1);
- WaitForAllOperations(device);
+ WaitForAllOperations();
buf.Unmap();
ASSERT_EQ(nullptr, buf.GetMappedRange());
@@ -945,7 +945,7 @@
buf.MapAsync(wgpu::MapMode::Read, 0, 4, ToMockBufferMapAsyncCallback, nullptr);
EXPECT_CALL(*mockBufferMapAsyncCallback, Call(WGPUBufferMapAsyncStatus_Success, _))
.Times(1);
- WaitForAllOperations(device);
+ WaitForAllOperations();
buf.Destroy();
ASSERT_EQ(nullptr, buf.GetMappedRange());
@@ -958,7 +958,7 @@
buf.MapAsync(wgpu::MapMode::Write, 0, 4, ToMockBufferMapAsyncCallback, nullptr);
EXPECT_CALL(*mockBufferMapAsyncCallback, Call(WGPUBufferMapAsyncStatus_Success, _))
.Times(1);
- WaitForAllOperations(device);
+ WaitForAllOperations();
buf.Destroy();
ASSERT_EQ(nullptr, buf.GetMappedRange());
@@ -972,7 +972,7 @@
buf.MapAsync(wgpu::MapMode::Read, 0, 4, ToMockBufferMapAsyncCallback, nullptr);
EXPECT_CALL(*mockBufferMapAsyncCallback, Call(WGPUBufferMapAsyncStatus_Success, _)).Times(1);
- WaitForAllOperations(device);
+ WaitForAllOperations();
ASSERT_EQ(nullptr, buf.GetMappedRange());
}
@@ -991,7 +991,7 @@
wgpu::Buffer buf = CreateMapReadBuffer(4);
buf.MapAsync(wgpu::MapMode::Read, 0, 4, nullptr, nullptr);
- WaitForAllOperations(device);
+ WaitForAllOperations();
ASSERT_NE(buf.GetConstMappedRange(), nullptr);
}
@@ -1001,7 +1001,7 @@
wgpu::Buffer buf = CreateMapWriteBuffer(4);
buf.MapAsync(wgpu::MapMode::Write, 0, 4, nullptr, nullptr);
- WaitForAllOperations(device);
+ WaitForAllOperations();
ASSERT_NE(buf.GetConstMappedRange(), nullptr);
ASSERT_EQ(buf.GetConstMappedRange(), buf.GetMappedRange());
@@ -1062,7 +1062,7 @@
{
wgpu::Buffer buffer = CreateMapWriteBuffer(8);
buffer.MapAsync(wgpu::MapMode::Write, 0, 8, nullptr, nullptr);
- WaitForAllOperations(device);
+ WaitForAllOperations();
EXPECT_NE(buffer.GetMappedRange(0, 8), nullptr);
}
@@ -1070,7 +1070,7 @@
{
wgpu::Buffer buffer = CreateMapWriteBuffer(8);
buffer.MapAsync(wgpu::MapMode::Write, 0, wgpu::kWholeMapSize, nullptr, nullptr);
- WaitForAllOperations(device);
+ WaitForAllOperations();
EXPECT_NE(buffer.GetMappedRange(0, 8), nullptr);
}
@@ -1078,7 +1078,7 @@
{
wgpu::Buffer buffer = CreateMapWriteBuffer(8);
buffer.MapAsync(wgpu::MapMode::Write, 0, wgpu::kWholeMapSize, nullptr, nullptr);
- WaitForAllOperations(device);
+ WaitForAllOperations();
EXPECT_NE(buffer.GetMappedRange(0, wgpu::kWholeMapSize), nullptr);
}
@@ -1086,7 +1086,7 @@
{
wgpu::Buffer buffer = CreateMapWriteBuffer(8);
buffer.MapAsync(wgpu::MapMode::Write, 0, 8, nullptr, nullptr);
- WaitForAllOperations(device);
+ WaitForAllOperations();
EXPECT_NE(buffer.GetMappedRange(8, 0), nullptr);
}
@@ -1094,7 +1094,7 @@
{
wgpu::Buffer buffer = CreateMapWriteBuffer(16);
buffer.MapAsync(wgpu::MapMode::Write, 0, 16, nullptr, nullptr);
- WaitForAllOperations(device);
+ WaitForAllOperations();
EXPECT_NE(buffer.GetMappedRange(8, 4), nullptr);
}
@@ -1102,7 +1102,7 @@
{
wgpu::Buffer buffer = CreateMapWriteBuffer(8);
buffer.MapAsync(wgpu::MapMode::Write, 0, 8, nullptr, nullptr);
- WaitForAllOperations(device);
+ WaitForAllOperations();
EXPECT_EQ(buffer.GetMappedRange(9, 0), nullptr);
EXPECT_EQ(buffer.GetMappedRange(16, 0), nullptr);
EXPECT_EQ(buffer.GetMappedRange(std::numeric_limits<size_t>::max(), 0), nullptr);
@@ -1112,7 +1112,7 @@
{
wgpu::Buffer buffer = CreateMapWriteBuffer(16);
buffer.MapAsync(wgpu::MapMode::Write, 8, 8, nullptr, nullptr);
- WaitForAllOperations(device);
+ WaitForAllOperations();
EXPECT_EQ(buffer.GetMappedRange(16, 4), nullptr);
EXPECT_EQ(buffer.GetMappedRange(24, 0), nullptr);
EXPECT_EQ(buffer.GetMappedRange(std::numeric_limits<size_t>::max(), 0), nullptr);
@@ -1122,7 +1122,7 @@
{
wgpu::Buffer buffer = CreateMapWriteBuffer(12);
buffer.MapAsync(wgpu::MapMode::Write, 0, 12, nullptr, nullptr);
- WaitForAllOperations(device);
+ WaitForAllOperations();
EXPECT_EQ(buffer.GetMappedRange(8, 5), nullptr);
EXPECT_EQ(buffer.GetMappedRange(8, 8), nullptr);
}
@@ -1131,7 +1131,7 @@
{
wgpu::Buffer buffer = CreateMapWriteBuffer(12);
buffer.MapAsync(wgpu::MapMode::Write, 0, 12, nullptr, nullptr);
- WaitForAllOperations(device);
+ WaitForAllOperations();
// set size to (max - 1) to avoid being equal to kWholeMapSize
EXPECT_EQ(buffer.GetMappedRange(8, std::numeric_limits<size_t>::max() - 1), nullptr);
}
@@ -1140,7 +1140,7 @@
{
wgpu::Buffer buffer = CreateMapWriteBuffer(12);
buffer.MapAsync(wgpu::MapMode::Write, 0, 8, nullptr, nullptr);
- WaitForAllOperations(device);
+ WaitForAllOperations();
EXPECT_EQ(buffer.GetMappedRange(0), nullptr);
}
@@ -1148,7 +1148,7 @@
{
wgpu::Buffer buffer = CreateMapWriteBuffer(12);
buffer.MapAsync(wgpu::MapMode::Write, 8, 4, nullptr, nullptr);
- WaitForAllOperations(device);
+ WaitForAllOperations();
EXPECT_EQ(buffer.GetMappedRange(7, 4), nullptr);
EXPECT_EQ(buffer.GetMappedRange(0, 4), nullptr);
EXPECT_EQ(buffer.GetMappedRange(0, 12), nullptr);
@@ -1237,7 +1237,7 @@
.Times(1);
buf.MapAsync(wgpu::MapMode::Read, 0, 4, ToMockBufferMapAsyncCallback, nullptr);
EXPECT_EQ(wgpu::BufferMapState::Pending, buf.GetMapState());
- WaitForAllOperations(device);
+ WaitForAllOperations();
EXPECT_EQ(wgpu::BufferMapState::Mapped, buf.GetMapState());
buf.Unmap();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
@@ -1254,7 +1254,7 @@
EXPECT_EQ(wgpu::BufferMapState::Pending, buf.GetMapState());
buf.Unmap();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
- WaitForAllOperations(device);
+ WaitForAllOperations();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
}
@@ -1266,7 +1266,7 @@
.Times(1);
buf.MapAsync(wgpu::MapMode::Read, 0, 4, ToMockBufferMapAsyncCallback, nullptr);
EXPECT_EQ(wgpu::BufferMapState::Pending, buf.GetMapState());
- WaitForAllOperations(device);
+ WaitForAllOperations();
EXPECT_EQ(wgpu::BufferMapState::Mapped, buf.GetMapState());
buf.Destroy();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
@@ -1283,7 +1283,7 @@
EXPECT_EQ(wgpu::BufferMapState::Pending, buf.GetMapState());
buf.Destroy();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
- WaitForAllOperations(device);
+ WaitForAllOperations();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
}
@@ -1295,7 +1295,7 @@
.Times(1);
buf.MapAsync(wgpu::MapMode::Write, 0, 4, ToMockBufferMapAsyncCallback, nullptr);
EXPECT_EQ(wgpu::BufferMapState::Pending, buf.GetMapState());
- WaitForAllOperations(device);
+ WaitForAllOperations();
EXPECT_EQ(wgpu::BufferMapState::Mapped, buf.GetMapState());
buf.Unmap();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
@@ -1312,7 +1312,7 @@
EXPECT_EQ(wgpu::BufferMapState::Pending, buf.GetMapState());
buf.Unmap();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
- WaitForAllOperations(device);
+ WaitForAllOperations();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
}
@@ -1324,7 +1324,7 @@
.Times(1);
buf.MapAsync(wgpu::MapMode::Write, 0, 4, ToMockBufferMapAsyncCallback, nullptr);
EXPECT_EQ(wgpu::BufferMapState::Pending, buf.GetMapState());
- WaitForAllOperations(device);
+ WaitForAllOperations();
EXPECT_EQ(wgpu::BufferMapState::Mapped, buf.GetMapState());
buf.Destroy();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
@@ -1341,7 +1341,7 @@
EXPECT_EQ(wgpu::BufferMapState::Pending, buf.GetMapState());
buf.Destroy();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
- WaitForAllOperations(device);
+ WaitForAllOperations();
EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
}
diff --git a/src/dawn/tests/unittests/validation/MultipleDeviceTests.cpp b/src/dawn/tests/unittests/validation/MultipleDeviceTests.cpp
index 14797af..c4d75ae 100644
--- a/src/dawn/tests/unittests/validation/MultipleDeviceTests.cpp
+++ b/src/dawn/tests/unittests/validation/MultipleDeviceTests.cpp
@@ -78,7 +78,7 @@
: wgpu::CallbackMode::AllowProcessEvents,
creationCallback.Callback());
- WaitForAllOperations(device);
+ WaitForAllOperations();
}
// CreateComputePipelineAsync errors if the shader module is created on a different device.
@@ -98,7 +98,7 @@
: wgpu::CallbackMode::AllowProcessEvents,
creationCallback.Callback());
- WaitForAllOperations(device);
+ WaitForAllOperations();
}
}
diff --git a/src/dawn/tests/unittests/validation/QueueOnSubmittedWorkDoneValidationTests.cpp b/src/dawn/tests/unittests/validation/QueueOnSubmittedWorkDoneValidationTests.cpp
index c0ae7a8..610fe22 100644
--- a/src/dawn/tests/unittests/validation/QueueOnSubmittedWorkDoneValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/QueueOnSubmittedWorkDoneValidationTests.cpp
@@ -58,5 +58,5 @@
EXPECT_CALL(*mockQueueWorkDoneCallback, Call(WGPUQueueWorkDoneStatus_Success, this)).Times(1);
device.GetQueue().OnSubmittedWorkDone(ToMockQueueWorkDone, this);
- WaitForAllOperations(device);
+ WaitForAllOperations();
}
diff --git a/src/dawn/tests/unittests/validation/ValidationTest.cpp b/src/dawn/tests/unittests/validation/ValidationTest.cpp
index 8256473..2472044 100644
--- a/src/dawn/tests/unittests/validation/ValidationTest.cpp
+++ b/src/dawn/tests/unittests/validation/ValidationTest.cpp
@@ -257,6 +257,15 @@
EXPECT_TRUE(mWireHelper->FlushServer());
}
+void ValidationTest::WaitForAllOperations() {
+ do {
+ FlushWire();
+ if (UsesWire()) {
+ instance.ProcessEvents();
+ }
+ } while (dawn::native::InstanceProcessEvents(mDawnInstance->Get()) || !mWireHelper->IsIdle());
+}
+
void ValidationTest::WaitForAllOperations(const wgpu::Device& waitDevice) {
bool done = false;
waitDevice.GetQueue().OnSubmittedWorkDone(
diff --git a/src/dawn/tests/unittests/validation/ValidationTest.h b/src/dawn/tests/unittests/validation/ValidationTest.h
index 974770a..3485585 100644
--- a/src/dawn/tests/unittests/validation/ValidationTest.h
+++ b/src/dawn/tests/unittests/validation/ValidationTest.h
@@ -144,6 +144,10 @@
bool UsesWire() const;
void FlushWire();
+
+ // TODO: crbug.com/42241461 - Remove overload that passes a device once we update tests to use
+ // new entry points.
+ void WaitForAllOperations();
void WaitForAllOperations(const wgpu::Device& device);
// Helper functions to create objects to test validation.
diff --git a/src/dawn/utils/TerribleCommandBuffer.cpp b/src/dawn/utils/TerribleCommandBuffer.cpp
index 0b193e3..5defa5c 100644
--- a/src/dawn/utils/TerribleCommandBuffer.cpp
+++ b/src/dawn/utils/TerribleCommandBuffer.cpp
@@ -67,4 +67,8 @@
return success;
}
+bool TerribleCommandBuffer::Empty() {
+ return mOffset == 0;
+}
+
} // namespace dawn::utils
diff --git a/src/dawn/utils/TerribleCommandBuffer.h b/src/dawn/utils/TerribleCommandBuffer.h
index 493d941..8c6b72a 100644
--- a/src/dawn/utils/TerribleCommandBuffer.h
+++ b/src/dawn/utils/TerribleCommandBuffer.h
@@ -44,6 +44,7 @@
void* GetCmdSpace(size_t size) override;
bool Flush() override;
+ bool Empty();
private:
raw_ptr<dawn::wire::CommandHandler> mHandler = nullptr;
diff --git a/src/dawn/utils/WireHelper.cpp b/src/dawn/utils/WireHelper.cpp
index 3214c5a..63f96d7 100644
--- a/src/dawn/utils/WireHelper.cpp
+++ b/src/dawn/utils/WireHelper.cpp
@@ -118,6 +118,8 @@
bool FlushServer() override { return true; }
+ bool IsIdle() override { return true; }
+
private:
const DawnProcTable& mProcs;
};
@@ -187,6 +189,8 @@
bool FlushServer() override { return mS2cBuf->Flush(); }
+ bool IsIdle() override { return mC2sBuf->Empty() && mS2cBuf->Empty(); }
+
private:
const DawnProcTable& mBackendProcs;
std::unique_ptr<dawn::utils::TerribleCommandBuffer> mC2sBuf;
diff --git a/src/dawn/utils/WireHelper.h b/src/dawn/utils/WireHelper.h
index 7c02388..61b5903 100644
--- a/src/dawn/utils/WireHelper.h
+++ b/src/dawn/utils/WireHelper.h
@@ -69,6 +69,8 @@
virtual bool FlushClient() = 0;
virtual bool FlushServer() = 0;
+
+ virtual bool IsIdle() = 0;
};
std::unique_ptr<WireHelper> CreateWireHelper(const DawnProcTable& procs,
diff --git a/src/dawn/wire/client/Instance.cpp b/src/dawn/wire/client/Instance.cpp
index 82cd558..b63845b 100644
--- a/src/dawn/wire/client/Instance.cpp
+++ b/src/dawn/wire/client/Instance.cpp
@@ -262,24 +262,6 @@
void Instance::ProcessEvents() {
GetEventManager().ProcessPollEvents();
-
- // TODO(crbug.com/dawn/1987): The responsibility of ProcessEvents here is a bit mixed. It both
- // processes events coming in from the server, and also prompts the server to check for and
- // forward over new events - which won't be received until *after* this client-side
- // ProcessEvents completes.
- //
- // Fixing this nicely probably requires the server to more self-sufficiently
- // forward the events, which is half of making the wire fully invisible to use (which we might
- // like to do, someday, but not soon). This is easy for immediate events (like requestDevice)
- // and thread-driven events (async pipeline creation), but harder for queue fences where we have
- // to wait on the backend and then trigger Dawn code to forward the event.
- //
- // In the meantime, we could maybe do this on client->server flush to keep this concern in the
- // wire instead of in the API itself, but otherwise it's not significantly better so we just
- // keep it here for now for backward compatibility.
- InstanceProcessEventsCmd cmd;
- cmd.self = ToAPI(this);
- GetClient()->SerializeCommand(cmd);
}
WGPUWaitStatus Instance::WaitAny(size_t count, WGPUFutureWaitInfo* infos, uint64_t timeoutNS) {