mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-19 01:46:35 +00:00
Remove Fences
Fences are no longer part of the WebGPU spec, and have been removed from Blink. Bug: dawn:22 Change-Id: I240c4c4107acfaf9facec88a43a38b5ff327c7a6 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/50702 Commit-Queue: Brandon Jones <bajones@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
committed by
Dawn LUCI CQ
parent
36cb5a86de
commit
a548578f67
@@ -197,7 +197,6 @@ test("dawn_unittests") {
|
||||
"unittests/validation/DynamicStateCommandValidationTests.cpp",
|
||||
"unittests/validation/ErrorScopeValidationTests.cpp",
|
||||
"unittests/validation/ExternalTextureTests.cpp",
|
||||
"unittests/validation/FenceValidationTests.cpp",
|
||||
"unittests/validation/GetBindGroupLayoutValidationTests.cpp",
|
||||
"unittests/validation/IndexBufferValidationTests.cpp",
|
||||
"unittests/validation/MinimumBufferSizeValidationTests.cpp",
|
||||
@@ -232,7 +231,6 @@ test("dawn_unittests") {
|
||||
"unittests/wire/WireDisconnectTests.cpp",
|
||||
"unittests/wire/WireErrorCallbackTests.cpp",
|
||||
"unittests/wire/WireExtensionTests.cpp",
|
||||
"unittests/wire/WireFenceTests.cpp",
|
||||
"unittests/wire/WireInjectDeviceTests.cpp",
|
||||
"unittests/wire/WireInjectSwapChainTests.cpp",
|
||||
"unittests/wire/WireInjectTextureTests.cpp",
|
||||
@@ -318,7 +316,6 @@ source_set("dawn_end2end_tests_sources") {
|
||||
"end2end/DynamicBufferOffsetTests.cpp",
|
||||
"end2end/EntryPointTests.cpp",
|
||||
"end2end/ExternalTextureTests.cpp",
|
||||
"end2end/FenceTests.cpp",
|
||||
"end2end/FirstIndexOffsetTests.cpp",
|
||||
"end2end/GpuMemorySynchronizationTests.cpp",
|
||||
"end2end/IndexFormatTests.cpp",
|
||||
|
||||
@@ -188,11 +188,6 @@ TEST_P(DeprecationTests, BindGroupLayoutEntryViewDimensionDefaulting) {
|
||||
}
|
||||
}
|
||||
|
||||
// Test that fences are deprecated.
|
||||
TEST_P(DeprecationTests, CreateFence) {
|
||||
EXPECT_DEPRECATION_WARNING(queue.CreateFence());
|
||||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(DeprecationTests,
|
||||
D3D12Backend(),
|
||||
MetalBackend(),
|
||||
|
||||
@@ -35,23 +35,6 @@ static void ToMockDeviceLostCallback(const char* message, void* userdata) {
|
||||
self->StartExpectDeviceError();
|
||||
}
|
||||
|
||||
class MockFenceOnCompletionCallback {
|
||||
public:
|
||||
MOCK_METHOD(void, Call, (WGPUFenceCompletionStatus status, void* userdata));
|
||||
};
|
||||
|
||||
static std::unique_ptr<MockFenceOnCompletionCallback> mockFenceOnCompletionCallback;
|
||||
static void ToMockFenceOnCompletionFails(WGPUFenceCompletionStatus status, void* userdata) {
|
||||
EXPECT_EQ(WGPUFenceCompletionStatus_DeviceLost, status);
|
||||
mockFenceOnCompletionCallback->Call(status, userdata);
|
||||
mockFenceOnCompletionCallback = nullptr;
|
||||
}
|
||||
static void ToMockFenceOnCompletionSucceeds(WGPUFenceCompletionStatus status, void* userdata) {
|
||||
EXPECT_EQ(WGPUFenceCompletionStatus_Success, status);
|
||||
mockFenceOnCompletionCallback->Call(status, userdata);
|
||||
mockFenceOnCompletionCallback = nullptr;
|
||||
}
|
||||
|
||||
class MockQueueWorkDoneCallback {
|
||||
public:
|
||||
MOCK_METHOD(void, Call, (WGPUQueueWorkDoneStatus status, void* userdata));
|
||||
@@ -70,13 +53,11 @@ class DeviceLostTest : public DawnTest {
|
||||
DawnTest::SetUp();
|
||||
DAWN_SKIP_TEST_IF(UsesWire());
|
||||
mockDeviceLostCallback = std::make_unique<MockDeviceLostCallback>();
|
||||
mockFenceOnCompletionCallback = std::make_unique<MockFenceOnCompletionCallback>();
|
||||
mockQueueWorkDoneCallback = std::make_unique<MockQueueWorkDoneCallback>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
mockDeviceLostCallback = nullptr;
|
||||
mockFenceOnCompletionCallback = nullptr;
|
||||
mockQueueWorkDoneCallback = nullptr;
|
||||
DawnTest::TearDown();
|
||||
}
|
||||
@@ -416,67 +397,6 @@ TEST_P(DeviceLostTest, CommandEncoderFinishFails) {
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
|
||||
// Test that CreateFenceFails when device is lost
|
||||
TEST_P(DeviceLostTest, CreateFenceFails) {
|
||||
SetCallbackAndLoseForTesting();
|
||||
|
||||
EXPECT_DEPRECATION_WARNING(ASSERT_DEVICE_ERROR(queue.CreateFence()));
|
||||
}
|
||||
|
||||
// Test that queue signal fails when device is lost
|
||||
TEST_P(DeviceLostTest, QueueSignalFenceFails) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
SetCallbackAndLoseForTesting();
|
||||
|
||||
ASSERT_DEVICE_ERROR(queue.Signal(fence, 3));
|
||||
|
||||
// callback should have device lost status
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_DeviceLost, nullptr))
|
||||
.Times(1);
|
||||
ASSERT_DEVICE_ERROR(fence.OnCompletion(2u, ToMockFenceOnCompletionFails, nullptr));
|
||||
|
||||
// completed value should not have changed from initial value
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 0u);
|
||||
}
|
||||
|
||||
// Test that Fence On Completion fails after device is lost
|
||||
TEST_P(DeviceLostTest, FenceOnCompletionFails) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
queue.Signal(fence, 2);
|
||||
|
||||
SetCallbackAndLoseForTesting();
|
||||
// callback should have device lost status
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_DeviceLost, nullptr))
|
||||
.Times(1);
|
||||
ASSERT_DEVICE_ERROR(fence.OnCompletion(2u, ToMockFenceOnCompletionFails, nullptr));
|
||||
ASSERT_DEVICE_ERROR(device.Tick());
|
||||
|
||||
// completed value is the last value signaled (all previous GPU operations are as if completed)
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 2u);
|
||||
}
|
||||
|
||||
// Test that Fence::OnCompletion callbacks with device lost status when device is lost after calling
|
||||
// OnCompletion
|
||||
TEST_P(DeviceLostTest, FenceOnCompletionBeforeLossFails) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
queue.Signal(fence, 2);
|
||||
|
||||
// callback should have device lost status
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_DeviceLost, nullptr))
|
||||
.Times(1);
|
||||
fence.OnCompletion(2u, ToMockFenceOnCompletionFails, nullptr);
|
||||
SetCallbackAndLoseForTesting();
|
||||
ASSERT_DEVICE_ERROR(device.Tick());
|
||||
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 2u);
|
||||
}
|
||||
|
||||
// Test that QueueOnSubmittedWorkDone fails after device is lost.
|
||||
TEST_P(DeviceLostTest, QueueOnSubmittedWorkDoneFails) {
|
||||
SetCallbackAndLoseForTesting();
|
||||
@@ -499,36 +419,6 @@ TEST_P(DeviceLostTest, QueueOnSubmittedWorkDoneBeforeLossFails) {
|
||||
ASSERT_DEVICE_ERROR(device.Tick());
|
||||
}
|
||||
|
||||
// Regression test for the Null backend not properly setting the completedSerial when
|
||||
// WaitForIdleForDestruction is called, causing the fence signaling to not be retired and an
|
||||
// ASSERT to fire.
|
||||
TEST_P(DeviceLostTest, AfterSubmitAndSerial) {
|
||||
queue.Submit(0, nullptr);
|
||||
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
queue.Signal(fence, 1);
|
||||
SetCallbackAndLoseForTesting();
|
||||
}
|
||||
|
||||
// Test that when you Signal, then Tick, then device lost, the fence completed value would be 2
|
||||
TEST_P(DeviceLostTest, FenceSignalTickOnCompletion) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
queue.Signal(fence, 2);
|
||||
WaitForAllOperations();
|
||||
|
||||
// callback should have device lost status
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, nullptr))
|
||||
.Times(1);
|
||||
fence.OnCompletion(2u, ToMockFenceOnCompletionSucceeds, nullptr);
|
||||
SetCallbackAndLoseForTesting();
|
||||
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 2u);
|
||||
}
|
||||
|
||||
// Test that LostForTesting can only be called on one time
|
||||
TEST_P(DeviceLostTest, LoseForTestingOnce) {
|
||||
// First LoseForTesting call should occur normally
|
||||
|
||||
@@ -1,277 +0,0 @@
|
||||
// Copyright 2018 The Dawn Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include "tests/DawnTest.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
|
||||
using namespace testing;
|
||||
|
||||
class MockFenceOnCompletionCallback {
|
||||
public:
|
||||
MOCK_METHOD(void, Call, (WGPUFenceCompletionStatus status, void* userdata));
|
||||
};
|
||||
|
||||
static std::unique_ptr<MockFenceOnCompletionCallback> mockFenceOnCompletionCallback;
|
||||
static void ToMockFenceOnCompletion(WGPUFenceCompletionStatus status, void* userdata) {
|
||||
mockFenceOnCompletionCallback->Call(status, userdata);
|
||||
}
|
||||
|
||||
class MockPopErrorScopeCallback {
|
||||
public:
|
||||
MOCK_METHOD(void, Call, (WGPUErrorType type, const char* message, void* userdata));
|
||||
};
|
||||
|
||||
static std::unique_ptr<MockPopErrorScopeCallback> mockPopErrorScopeCallback;
|
||||
static void ToMockPopErrorScopeCallback(WGPUErrorType type, const char* message, void* userdata) {
|
||||
mockPopErrorScopeCallback->Call(type, message, userdata);
|
||||
}
|
||||
|
||||
class FenceTests : public DawnTest {
|
||||
private:
|
||||
struct CallbackInfo {
|
||||
FenceTests* test;
|
||||
uint64_t value;
|
||||
WGPUFenceCompletionStatus status;
|
||||
int32_t callIndex = -1; // If this is -1, the callback was not called
|
||||
|
||||
void Update(WGPUFenceCompletionStatus status) {
|
||||
this->callIndex = test->mCallIndex++;
|
||||
this->status = status;
|
||||
}
|
||||
};
|
||||
|
||||
int32_t mCallIndex;
|
||||
|
||||
protected:
|
||||
FenceTests() : mCallIndex(0) {
|
||||
}
|
||||
|
||||
void SetUp() override {
|
||||
DawnTest::SetUp();
|
||||
mockFenceOnCompletionCallback = std::make_unique<MockFenceOnCompletionCallback>();
|
||||
mockPopErrorScopeCallback = std::make_unique<MockPopErrorScopeCallback>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
mockFenceOnCompletionCallback = nullptr;
|
||||
mockPopErrorScopeCallback = nullptr;
|
||||
DawnTest::TearDown();
|
||||
}
|
||||
|
||||
void WaitForCompletedValue(wgpu::Fence fence, uint64_t completedValue) {
|
||||
while (fence.GetCompletedValue() < completedValue) {
|
||||
WaitABit();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Test that signaling a fence updates the completed value
|
||||
TEST_P(FenceTests, SimpleSignal) {
|
||||
wgpu::FenceDescriptor descriptor;
|
||||
descriptor.initialValue = 1u;
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence(&descriptor));
|
||||
|
||||
// Completed value starts at initial value
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 1u);
|
||||
|
||||
queue.Signal(fence, 2);
|
||||
WaitForCompletedValue(fence, 2);
|
||||
|
||||
// Completed value updates to signaled value
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 2u);
|
||||
}
|
||||
|
||||
// Test callbacks are called in increasing order of fence completion value
|
||||
TEST_P(FenceTests, OnCompletionOrdering) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
queue.Signal(fence, 4);
|
||||
|
||||
{
|
||||
testing::InSequence s;
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback,
|
||||
Call(WGPUFenceCompletionStatus_Success, this + 0))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback,
|
||||
Call(WGPUFenceCompletionStatus_Success, this + 1))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback,
|
||||
Call(WGPUFenceCompletionStatus_Success, this + 2))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback,
|
||||
Call(WGPUFenceCompletionStatus_Success, this + 3))
|
||||
.Times(1);
|
||||
}
|
||||
|
||||
fence.OnCompletion(2u, ToMockFenceOnCompletion, this + 2);
|
||||
fence.OnCompletion(0u, ToMockFenceOnCompletion, this + 0);
|
||||
fence.OnCompletion(3u, ToMockFenceOnCompletion, this + 3);
|
||||
fence.OnCompletion(1u, ToMockFenceOnCompletion, this + 1);
|
||||
|
||||
WaitForCompletedValue(fence, 4);
|
||||
}
|
||||
|
||||
// Test callbacks still occur if Queue::Signal happens multiple times
|
||||
TEST_P(FenceTests, MultipleSignalOnCompletion) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
queue.Signal(fence, 2);
|
||||
queue.Signal(fence, 4);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, nullptr))
|
||||
.Times(1);
|
||||
fence.OnCompletion(3u, ToMockFenceOnCompletion, nullptr);
|
||||
|
||||
WaitForCompletedValue(fence, 4);
|
||||
}
|
||||
|
||||
// Test callbacks still occur if Queue::Signal and fence::OnCompletion happens multiple times
|
||||
TEST_P(FenceTests, SignalOnCompletionWait) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
queue.Signal(fence, 2);
|
||||
queue.Signal(fence, 6);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 2))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 6))
|
||||
.Times(1);
|
||||
|
||||
fence.OnCompletion(1u, ToMockFenceOnCompletion, this + 2);
|
||||
fence.OnCompletion(5u, ToMockFenceOnCompletion, this + 6);
|
||||
|
||||
WaitForCompletedValue(fence, 6);
|
||||
}
|
||||
|
||||
// Test callbacks still occur if Queue::Signal and fence::OnCompletion happens multiple times
|
||||
TEST_P(FenceTests, SignalOnCompletionWaitStaggered) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
queue.Signal(fence, 2);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 2))
|
||||
.Times(1);
|
||||
fence.OnCompletion(1u, ToMockFenceOnCompletion, this + 2);
|
||||
|
||||
queue.Signal(fence, 4);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 4))
|
||||
.Times(1);
|
||||
fence.OnCompletion(3u, ToMockFenceOnCompletion, this + 4);
|
||||
|
||||
WaitForCompletedValue(fence, 4);
|
||||
}
|
||||
|
||||
// Test all callbacks are called if they are added for the same fence value
|
||||
TEST_P(FenceTests, OnCompletionMultipleCallbacks) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
queue.Signal(fence, 4);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 0))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 1))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 2))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 3))
|
||||
.Times(1);
|
||||
|
||||
fence.OnCompletion(4u, ToMockFenceOnCompletion, this + 0);
|
||||
fence.OnCompletion(4u, ToMockFenceOnCompletion, this + 1);
|
||||
fence.OnCompletion(4u, ToMockFenceOnCompletion, this + 2);
|
||||
fence.OnCompletion(4u, ToMockFenceOnCompletion, this + 3);
|
||||
|
||||
WaitForCompletedValue(fence, 4u);
|
||||
}
|
||||
|
||||
// TODO(enga): Enable when fence is removed from fence signal tracker
|
||||
// Currently it holds a reference and is not destructed
|
||||
TEST_P(FenceTests, DISABLED_DestroyBeforeOnCompletionEnd) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
// The fence in this block will be deleted when it goes out of scope
|
||||
{
|
||||
wgpu::Fence testFence;
|
||||
EXPECT_DEPRECATION_WARNING(testFence = queue.CreateFence());
|
||||
|
||||
queue.Signal(testFence, 4);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback,
|
||||
Call(WGPUFenceCompletionStatus_Unknown, this + 0))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback,
|
||||
Call(WGPUFenceCompletionStatus_Unknown, this + 1))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback,
|
||||
Call(WGPUFenceCompletionStatus_Unknown, this + 2))
|
||||
.Times(1);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback,
|
||||
Call(WGPUFenceCompletionStatus_Unknown, this + 3))
|
||||
.Times(1);
|
||||
|
||||
testFence.OnCompletion(1u, ToMockFenceOnCompletion, this + 0);
|
||||
testFence.OnCompletion(2u, ToMockFenceOnCompletion, this + 1);
|
||||
testFence.OnCompletion(2u, ToMockFenceOnCompletion, this + 2);
|
||||
testFence.OnCompletion(3u, ToMockFenceOnCompletion, this + 3);
|
||||
}
|
||||
|
||||
// Wait for another fence to be sure all callbacks have cleared
|
||||
queue.Signal(fence, 1);
|
||||
WaitForCompletedValue(fence, 1);
|
||||
}
|
||||
|
||||
// Regression test that validation errors that are tracked client-side are captured
|
||||
// in error scopes.
|
||||
TEST_P(FenceTests, ClientValidationErrorInErrorScope) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
queue.Signal(fence, 4);
|
||||
|
||||
device.PushErrorScope(wgpu::ErrorFilter::Validation);
|
||||
queue.Signal(fence, 2);
|
||||
|
||||
EXPECT_CALL(*mockPopErrorScopeCallback, Call(WGPUErrorType_Validation, _, this)).Times(1);
|
||||
device.PopErrorScope(ToMockPopErrorScopeCallback, this);
|
||||
|
||||
WaitForCompletedValue(fence, 4);
|
||||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(FenceTests,
|
||||
D3D12Backend(),
|
||||
MetalBackend(),
|
||||
OpenGLBackend(),
|
||||
OpenGLESBackend(),
|
||||
VulkanBackend());
|
||||
@@ -28,17 +28,6 @@ static void ToMockMapCallback(WGPUBufferMapAsyncStatus status, void* userdata) {
|
||||
mockMapCallback->Call(status, userdata);
|
||||
}
|
||||
|
||||
class MockFenceOnCompletionCallback {
|
||||
public:
|
||||
MOCK_METHOD(void, Call, (WGPUFenceCompletionStatus status, void* userdata));
|
||||
};
|
||||
|
||||
static std::unique_ptr<MockFenceOnCompletionCallback> mockFenceOnCompletionCallback;
|
||||
static void ToMockFenceOnCompletion(WGPUFenceCompletionStatus status, void* userdata) {
|
||||
EXPECT_EQ(status, WGPUFenceCompletionStatus_Success);
|
||||
mockFenceOnCompletionCallback->Call(status, userdata);
|
||||
}
|
||||
|
||||
class MockQueueWorkDoneCallback {
|
||||
public:
|
||||
MOCK_METHOD(void, Call, (WGPUQueueWorkDoneStatus status, void* userdata));
|
||||
@@ -55,7 +44,6 @@ class QueueTimelineTests : public DawnTest {
|
||||
DawnTest::SetUp();
|
||||
|
||||
mockMapCallback = std::make_unique<MockMapCallback>();
|
||||
mockFenceOnCompletionCallback = std::make_unique<MockFenceOnCompletionCallback>();
|
||||
mockQueueWorkDoneCallback = std::make_unique<MockQueueWorkDoneCallback>();
|
||||
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
@@ -66,7 +54,6 @@ class QueueTimelineTests : public DawnTest {
|
||||
|
||||
void TearDown() override {
|
||||
mockMapCallback = nullptr;
|
||||
mockFenceOnCompletionCallback = nullptr;
|
||||
mockQueueWorkDoneCallback = nullptr;
|
||||
DawnTest::TearDown();
|
||||
}
|
||||
@@ -74,27 +61,6 @@ class QueueTimelineTests : public DawnTest {
|
||||
wgpu::Buffer mMapReadBuffer;
|
||||
};
|
||||
|
||||
// Test that mMapReadBuffer.MapAsync callback happens before fence.OnCompletion callback
|
||||
// when queue.Signal is called after mMapReadBuffer.MapAsync. The callback order should
|
||||
// happen in the order the functions are called.
|
||||
TEST_P(QueueTimelineTests, MapReadSignalOnComplete) {
|
||||
testing::InSequence sequence;
|
||||
EXPECT_CALL(*mockMapCallback, Call(WGPUBufferMapAsyncStatus_Success, this)).Times(1);
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this))
|
||||
.Times(1);
|
||||
|
||||
mMapReadBuffer.MapAsync(wgpu::MapMode::Read, 0, 0, ToMockMapCallback, this);
|
||||
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
|
||||
queue.Signal(fence, 1);
|
||||
fence.OnCompletion(1u, ToMockFenceOnCompletion, this);
|
||||
|
||||
WaitForAllOperations();
|
||||
mMapReadBuffer.Unmap();
|
||||
}
|
||||
|
||||
// Test that mMapReadBuffer.MapAsync callback happens before queue.OnWorkDone callback
|
||||
// when queue.OnSubmittedWorkDone is called after mMapReadBuffer.MapAsync. The callback order should
|
||||
// happen in the order the functions are called.
|
||||
@@ -111,26 +77,6 @@ TEST_P(QueueTimelineTests, MapRead_OnWorkDone) {
|
||||
mMapReadBuffer.Unmap();
|
||||
}
|
||||
|
||||
// Test that fence.OnCompletion callback happens before mMapReadBuffer.MapAsync callback when
|
||||
// queue.OnSubmittedWorkDone is called before mMapReadBuffer.MapAsync. The callback order should
|
||||
// happen in the order the functions are called.
|
||||
TEST_P(QueueTimelineTests, SignalMapReadOnComplete) {
|
||||
testing::InSequence sequence;
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*mockMapCallback, Call(WGPUBufferMapAsyncStatus_Success, this)).Times(1);
|
||||
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
queue.Signal(fence, 2);
|
||||
|
||||
mMapReadBuffer.MapAsync(wgpu::MapMode::Read, 0, 0, ToMockMapCallback, this);
|
||||
|
||||
fence.OnCompletion(2u, ToMockFenceOnCompletion, this);
|
||||
WaitForAllOperations();
|
||||
mMapReadBuffer.Unmap();
|
||||
}
|
||||
|
||||
// Test that queue.OnWorkDone callback happens before mMapReadBuffer.MapAsync callback when
|
||||
// queue.Signal is called before mMapReadBuffer.MapAsync. The callback order should
|
||||
// happen in the order the functions are called.
|
||||
@@ -147,65 +93,6 @@ TEST_P(QueueTimelineTests, OnWorkDone_MapRead) {
|
||||
mMapReadBuffer.Unmap();
|
||||
}
|
||||
|
||||
// Test that fence.OnCompletion callback happens before mMapReadBuffer.MapAsync callback when
|
||||
// queue.Signal is called before mMapReadBuffer.MapAsync. The callback order should
|
||||
// happen in the order the functions are called
|
||||
TEST_P(QueueTimelineTests, SignalOnCompleteMapRead) {
|
||||
testing::InSequence sequence;
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*mockMapCallback, Call(WGPUBufferMapAsyncStatus_Success, this)).Times(1);
|
||||
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
queue.Signal(fence, 2);
|
||||
|
||||
fence.OnCompletion(2u, ToMockFenceOnCompletion, this);
|
||||
|
||||
mMapReadBuffer.MapAsync(wgpu::MapMode::Read, 0, 0, ToMockMapCallback, this);
|
||||
|
||||
WaitForAllOperations();
|
||||
mMapReadBuffer.Unmap();
|
||||
}
|
||||
|
||||
// Test a complicated case with many signals surrounding a buffer mapping.
|
||||
TEST_P(QueueTimelineTests, SurroundWithFenceSignals) {
|
||||
testing::InSequence sequence;
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 0))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 2))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 3))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*mockMapCallback, Call(WGPUBufferMapAsyncStatus_Success, this)).Times(1);
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 5))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 6))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 8))
|
||||
.Times(1);
|
||||
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
queue.Signal(fence, 2);
|
||||
queue.Signal(fence, 4);
|
||||
|
||||
fence.OnCompletion(1u, ToMockFenceOnCompletion, this + 0);
|
||||
fence.OnCompletion(2u, ToMockFenceOnCompletion, this + 2);
|
||||
|
||||
mMapReadBuffer.MapAsync(wgpu::MapMode::Read, 0, 0, ToMockMapCallback, this);
|
||||
queue.Signal(fence, 6);
|
||||
fence.OnCompletion(3u, ToMockFenceOnCompletion, this + 3);
|
||||
fence.OnCompletion(5u, ToMockFenceOnCompletion, this + 5);
|
||||
fence.OnCompletion(6u, ToMockFenceOnCompletion, this + 6);
|
||||
|
||||
queue.Signal(fence, 8);
|
||||
fence.OnCompletion(8u, ToMockFenceOnCompletion, this + 8);
|
||||
|
||||
WaitForAllOperations();
|
||||
mMapReadBuffer.Unmap();
|
||||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(QueueTimelineTests,
|
||||
D3D12Backend(),
|
||||
MetalBackend(),
|
||||
|
||||
@@ -31,11 +31,22 @@ static void ToMockDevicePopErrorScopeCallback(WGPUErrorType type,
|
||||
mockDevicePopErrorScopeCallback->Call(type, message, userdata);
|
||||
}
|
||||
|
||||
class MockQueueWorkDoneCallback {
|
||||
public:
|
||||
MOCK_METHOD(void, Call, (WGPUQueueWorkDoneStatus status, void* userdata));
|
||||
};
|
||||
|
||||
static std::unique_ptr<MockQueueWorkDoneCallback> mockQueueWorkDoneCallback;
|
||||
static void ToMockQueueWorkDone(WGPUQueueWorkDoneStatus status, void* userdata) {
|
||||
mockQueueWorkDoneCallback->Call(status, userdata);
|
||||
}
|
||||
|
||||
class ErrorScopeValidationTest : public ValidationTest {
|
||||
private:
|
||||
void SetUp() override {
|
||||
ValidationTest::SetUp();
|
||||
mockDevicePopErrorScopeCallback = std::make_unique<MockDevicePopErrorScopeCallback>();
|
||||
mockQueueWorkDoneCallback = std::make_unique<MockQueueWorkDoneCallback>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
@@ -43,6 +54,7 @@ class ErrorScopeValidationTest : public ValidationTest {
|
||||
|
||||
// Delete mocks so that expectations are checked
|
||||
mockDevicePopErrorScopeCallback = nullptr;
|
||||
mockQueueWorkDoneCallback = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -141,31 +153,6 @@ TEST_F(ErrorScopeValidationTest, PushPopBalanced) {
|
||||
}
|
||||
}
|
||||
|
||||
// Test that error scopes call their callbacks before an enclosed Queue::Submit
|
||||
// completes
|
||||
TEST_F(ErrorScopeValidationTest, EnclosedQueueSubmit) {
|
||||
wgpu::Queue queue = device.GetQueue();
|
||||
|
||||
device.PushErrorScope(wgpu::ErrorFilter::OutOfMemory);
|
||||
|
||||
queue.Submit(0, nullptr);
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
queue.Signal(fence, 1);
|
||||
|
||||
testing::Sequence seq;
|
||||
|
||||
MockCallback<WGPUFenceOnCompletionCallback> fenceCallback;
|
||||
fence.OnCompletion(1, fenceCallback.Callback(), fenceCallback.MakeUserdata(this));
|
||||
|
||||
MockCallback<WGPUErrorCallback> errorScopeCallback;
|
||||
EXPECT_CALL(errorScopeCallback, Call(WGPUErrorType_NoError, _, this + 1)).InSequence(seq);
|
||||
device.PopErrorScope(errorScopeCallback.Callback(), errorScopeCallback.MakeUserdata(this + 1));
|
||||
|
||||
EXPECT_CALL(fenceCallback, Call(WGPUFenceCompletionStatus_Success, this)).InSequence(seq);
|
||||
WaitForAllOperations(device);
|
||||
}
|
||||
|
||||
// Test that parent error scopes also call their callbacks before an enclosed Queue::Submit
|
||||
// completes
|
||||
TEST_F(ErrorScopeValidationTest, EnclosedQueueSubmitNested) {
|
||||
@@ -175,15 +162,10 @@ TEST_F(ErrorScopeValidationTest, EnclosedQueueSubmitNested) {
|
||||
device.PushErrorScope(wgpu::ErrorFilter::OutOfMemory);
|
||||
|
||||
queue.Submit(0, nullptr);
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
queue.Signal(fence, 1);
|
||||
queue.OnSubmittedWorkDone(0u, ToMockQueueWorkDone, this);
|
||||
|
||||
testing::Sequence seq;
|
||||
|
||||
MockCallback<WGPUFenceOnCompletionCallback> fenceCallback;
|
||||
fence.OnCompletion(1, fenceCallback.Callback(), fenceCallback.MakeUserdata(this));
|
||||
|
||||
MockCallback<WGPUErrorCallback> errorScopeCallback2;
|
||||
EXPECT_CALL(errorScopeCallback2, Call(WGPUErrorType_NoError, _, this + 1)).InSequence(seq);
|
||||
device.PopErrorScope(errorScopeCallback2.Callback(),
|
||||
@@ -194,7 +176,8 @@ TEST_F(ErrorScopeValidationTest, EnclosedQueueSubmitNested) {
|
||||
device.PopErrorScope(errorScopeCallback1.Callback(),
|
||||
errorScopeCallback1.MakeUserdata(this + 2));
|
||||
|
||||
EXPECT_CALL(fenceCallback, Call(WGPUFenceCompletionStatus_Success, this)).InSequence(seq);
|
||||
EXPECT_CALL(*mockQueueWorkDoneCallback, Call(WGPUQueueWorkDoneStatus_Success, this))
|
||||
.InSequence(seq);
|
||||
WaitForAllOperations(device);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,235 +0,0 @@
|
||||
// Copyright 2018 The Dawn Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "tests/unittests/validation/ValidationTest.h"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
using namespace testing;
|
||||
|
||||
class MockFenceOnCompletionCallback {
|
||||
public:
|
||||
MOCK_METHOD(void, Call, (WGPUFenceCompletionStatus status, void* userdata));
|
||||
};
|
||||
|
||||
struct FenceOnCompletionExpectation {
|
||||
wgpu::Fence fence;
|
||||
uint64_t value;
|
||||
WGPUFenceCompletionStatus status;
|
||||
};
|
||||
|
||||
static std::unique_ptr<MockFenceOnCompletionCallback> mockFenceOnCompletionCallback;
|
||||
static void ToMockFenceOnCompletion(WGPUFenceCompletionStatus status, void* userdata) {
|
||||
mockFenceOnCompletionCallback->Call(status, userdata);
|
||||
}
|
||||
|
||||
class FenceValidationTest : public ValidationTest {
|
||||
protected:
|
||||
void TestOnCompletion(wgpu::Fence fence, uint64_t value, WGPUFenceCompletionStatus status) {
|
||||
FenceOnCompletionExpectation* expectation = new FenceOnCompletionExpectation;
|
||||
expectation->fence = fence;
|
||||
expectation->value = value;
|
||||
expectation->status = status;
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(status, expectation)).Times(1);
|
||||
fence.OnCompletion(value, ToMockFenceOnCompletion, expectation);
|
||||
}
|
||||
|
||||
wgpu::Queue queue;
|
||||
|
||||
private:
|
||||
void SetUp() override {
|
||||
ValidationTest::SetUp();
|
||||
|
||||
mockFenceOnCompletionCallback = std::make_unique<MockFenceOnCompletionCallback>();
|
||||
queue = device.GetQueue();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
// Delete mocks so that expectations are checked
|
||||
mockFenceOnCompletionCallback = nullptr;
|
||||
|
||||
ValidationTest::TearDown();
|
||||
}
|
||||
};
|
||||
|
||||
// Test cases where creation should succeed
|
||||
TEST_F(FenceValidationTest, CreationSuccess) {
|
||||
// Success
|
||||
{
|
||||
wgpu::FenceDescriptor descriptor;
|
||||
descriptor.initialValue = 0;
|
||||
EXPECT_DEPRECATION_WARNING(queue.CreateFence(&descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
// Creation succeeds if no descriptor is provided
|
||||
TEST_F(FenceValidationTest, DefaultDescriptor) {
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence());
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 0u);
|
||||
}
|
||||
|
||||
TEST_F(FenceValidationTest, GetCompletedValue) {
|
||||
// Starts at initial value
|
||||
{
|
||||
wgpu::FenceDescriptor descriptor;
|
||||
descriptor.initialValue = 1;
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence(&descriptor));
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 1u);
|
||||
}
|
||||
}
|
||||
|
||||
// Test that OnCompletion handlers are called immediately for
|
||||
// already completed fence values
|
||||
TEST_F(FenceValidationTest, OnCompletionImmediate) {
|
||||
// TODO(crbug.com/dawn/653): This has wrong different behavior on the wire, but fences will be
|
||||
// removed soon.
|
||||
DAWN_SKIP_TEST_IF(UsesWire());
|
||||
|
||||
wgpu::FenceDescriptor descriptor;
|
||||
descriptor.initialValue = 1;
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence(&descriptor));
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 0))
|
||||
.Times(1);
|
||||
fence.OnCompletion(0u, ToMockFenceOnCompletion, this + 0);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this + 1))
|
||||
.Times(1);
|
||||
fence.OnCompletion(1u, ToMockFenceOnCompletion, this + 1);
|
||||
}
|
||||
|
||||
// Test setting OnCompletion handlers for values > signaled value
|
||||
TEST_F(FenceValidationTest, OnCompletionLargerThanSignaled) {
|
||||
wgpu::FenceDescriptor descriptor;
|
||||
descriptor.initialValue = 1;
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence(&descriptor));
|
||||
|
||||
// Cannot signal for values > signaled value
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Error, nullptr))
|
||||
.Times(1);
|
||||
ASSERT_DEVICE_ERROR(fence.OnCompletion(2u, ToMockFenceOnCompletion, nullptr));
|
||||
|
||||
// Can set handler after signaling
|
||||
queue.Signal(fence, 2);
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, nullptr))
|
||||
.Times(1);
|
||||
fence.OnCompletion(2u, ToMockFenceOnCompletion, nullptr);
|
||||
|
||||
WaitForAllOperations(device);
|
||||
}
|
||||
|
||||
TEST_F(FenceValidationTest, GetCompletedValueInsideCallback) {
|
||||
// TODO(crbug.com/dawn/653): This has wrong different behavior on the wire, but fences will be
|
||||
// removed soon.
|
||||
DAWN_SKIP_TEST_IF(UsesWire());
|
||||
|
||||
wgpu::FenceDescriptor descriptor;
|
||||
descriptor.initialValue = 1;
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence(&descriptor));
|
||||
|
||||
queue.Signal(fence, 3);
|
||||
fence.OnCompletion(2u, ToMockFenceOnCompletion, nullptr);
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, nullptr))
|
||||
.WillOnce(Invoke([&](WGPUFenceCompletionStatus status, void* userdata) {
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 3u);
|
||||
}));
|
||||
|
||||
WaitForAllOperations(device);
|
||||
}
|
||||
|
||||
TEST_F(FenceValidationTest, GetCompletedValueAfterCallback) {
|
||||
wgpu::FenceDescriptor descriptor;
|
||||
descriptor.initialValue = 1;
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence(&descriptor));
|
||||
|
||||
queue.Signal(fence, 2);
|
||||
fence.OnCompletion(2u, ToMockFenceOnCompletion, nullptr);
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, nullptr))
|
||||
.Times(1);
|
||||
|
||||
WaitForAllOperations(device);
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 2u);
|
||||
}
|
||||
|
||||
TEST_F(FenceValidationTest, SignalError) {
|
||||
wgpu::FenceDescriptor descriptor;
|
||||
descriptor.initialValue = 1;
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence(&descriptor));
|
||||
|
||||
// value < fence signaled value
|
||||
ASSERT_DEVICE_ERROR(queue.Signal(fence, 0));
|
||||
|
||||
// value == fence signaled value
|
||||
ASSERT_DEVICE_ERROR(queue.Signal(fence, 1));
|
||||
}
|
||||
|
||||
TEST_F(FenceValidationTest, SignalSuccess) {
|
||||
wgpu::FenceDescriptor descriptor;
|
||||
descriptor.initialValue = 1;
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence(&descriptor));
|
||||
|
||||
// Success
|
||||
queue.Signal(fence, 2);
|
||||
WaitForAllOperations(device);
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 2u);
|
||||
|
||||
// Success increasing fence value by more than 1
|
||||
queue.Signal(fence, 6);
|
||||
WaitForAllOperations(device);
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 6u);
|
||||
}
|
||||
|
||||
// Test it is invalid to signal a fence on a different queue than it was created on
|
||||
// DISABLED until we have support for multiple queues
|
||||
TEST_F(FenceValidationTest, DISABLED_SignalWrongQueue) {
|
||||
wgpu::Queue queue2 = device.GetQueue();
|
||||
|
||||
wgpu::FenceDescriptor descriptor;
|
||||
descriptor.initialValue = 1;
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence(&descriptor));
|
||||
|
||||
ASSERT_DEVICE_ERROR(queue2.Signal(fence, 2));
|
||||
}
|
||||
|
||||
// Test that signaling a fence on a wrong queue does not update fence signaled value
|
||||
// DISABLED until we have support for multiple queues
|
||||
TEST_F(FenceValidationTest, DISABLED_SignalWrongQueueDoesNotUpdateValue) {
|
||||
wgpu::Queue queue2 = device.GetQueue();
|
||||
|
||||
wgpu::FenceDescriptor descriptor;
|
||||
descriptor.initialValue = 1;
|
||||
wgpu::Fence fence;
|
||||
EXPECT_DEPRECATION_WARNING(fence = queue.CreateFence(&descriptor));
|
||||
|
||||
ASSERT_DEVICE_ERROR(queue2.Signal(fence, 2));
|
||||
|
||||
// Fence value should be unchanged.
|
||||
WaitForAllOperations(device);
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 1u);
|
||||
|
||||
// Signaling with 2 on the correct queue should succeed
|
||||
queue.Signal(fence, 2);
|
||||
WaitForAllOperations(device);
|
||||
EXPECT_EQ(fence.GetCompletedValue(), 2u);
|
||||
}
|
||||
@@ -1,268 +0,0 @@
|
||||
// Copyright 2019 The Dawn Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "tests/unittests/wire/WireTest.h"
|
||||
|
||||
#include "dawn_wire/WireClient.h"
|
||||
|
||||
using namespace testing;
|
||||
using namespace dawn_wire;
|
||||
|
||||
namespace {
|
||||
|
||||
class MockFenceOnCompletionCallback {
|
||||
public:
|
||||
MOCK_METHOD(void, Call, (WGPUFenceCompletionStatus status, void* userdata));
|
||||
};
|
||||
|
||||
std::unique_ptr<StrictMock<MockFenceOnCompletionCallback>> mockFenceOnCompletionCallback;
|
||||
void ToMockFenceOnCompletion(WGPUFenceCompletionStatus status, void* userdata) {
|
||||
mockFenceOnCompletionCallback->Call(status, userdata);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
class WireFenceTests : public WireTest {
|
||||
public:
|
||||
WireFenceTests() {
|
||||
}
|
||||
~WireFenceTests() override = default;
|
||||
|
||||
void SetUp() override {
|
||||
WireTest::SetUp();
|
||||
|
||||
mockFenceOnCompletionCallback =
|
||||
std::make_unique<StrictMock<MockFenceOnCompletionCallback>>();
|
||||
|
||||
{
|
||||
WGPUFenceDescriptor descriptor = {};
|
||||
descriptor.initialValue = 1;
|
||||
|
||||
apiFence = api.GetNewFence();
|
||||
fence = wgpuQueueCreateFence(queue, &descriptor);
|
||||
|
||||
EXPECT_CALL(api, QueueCreateFence(apiQueue, _)).WillOnce(Return(apiFence));
|
||||
FlushClient();
|
||||
}
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
WireTest::TearDown();
|
||||
|
||||
mockFenceOnCompletionCallback = nullptr;
|
||||
}
|
||||
|
||||
void FlushServer() {
|
||||
WireTest::FlushServer();
|
||||
|
||||
Mock::VerifyAndClearExpectations(&mockFenceOnCompletionCallback);
|
||||
}
|
||||
|
||||
protected:
|
||||
void DoQueueSignal(uint64_t signalValue,
|
||||
WGPUFenceCompletionStatus status = WGPUFenceCompletionStatus_Success) {
|
||||
wgpuQueueSignal(queue, fence, signalValue);
|
||||
EXPECT_CALL(api, QueueSignal(apiQueue, apiFence, signalValue)).Times(1);
|
||||
|
||||
// This callback is generated to update the completedValue of the fence
|
||||
// on the client
|
||||
EXPECT_CALL(api, OnFenceOnCompletion(apiFence, signalValue, _, _))
|
||||
.WillOnce(
|
||||
InvokeWithoutArgs([=]() { api.CallFenceOnCompletionCallback(apiFence, status); }))
|
||||
.RetiresOnSaturation();
|
||||
}
|
||||
|
||||
// A successfully created fence
|
||||
WGPUFence fence;
|
||||
WGPUFence apiFence;
|
||||
};
|
||||
|
||||
// Check that signaling a fence succeeds
|
||||
TEST_F(WireFenceTests, QueueSignalSuccess) {
|
||||
DoQueueSignal(2u);
|
||||
FlushClient();
|
||||
FlushServer();
|
||||
|
||||
EXPECT_EQ(wgpuFenceGetCompletedValue(fence), 2u);
|
||||
}
|
||||
|
||||
// Check that signaling a fence twice succeeds
|
||||
TEST_F(WireFenceTests, QueueSignalIncreasing) {
|
||||
DoQueueSignal(2u);
|
||||
DoQueueSignal(3u);
|
||||
FlushClient();
|
||||
FlushServer();
|
||||
|
||||
EXPECT_EQ(wgpuFenceGetCompletedValue(fence), 3u);
|
||||
}
|
||||
|
||||
// Check that an error in queue signal does not update the completed value.
|
||||
TEST_F(WireFenceTests, QueueSignalValidationError) {
|
||||
DoQueueSignal(2u);
|
||||
DoQueueSignal(1u, WGPUFenceCompletionStatus_Error);
|
||||
FlushClient();
|
||||
FlushServer();
|
||||
|
||||
// Value should stay at 2 and not be updated to 1.
|
||||
EXPECT_EQ(wgpuFenceGetCompletedValue(fence), 2u);
|
||||
}
|
||||
|
||||
// Check that a success in the on completion callback is forwarded to the client.
|
||||
TEST_F(WireFenceTests, OnCompletionSuccess) {
|
||||
wgpuFenceOnCompletion(fence, 0, ToMockFenceOnCompletion, nullptr);
|
||||
EXPECT_CALL(api, OnFenceOnCompletion(apiFence, 0u, _, _)).WillOnce(InvokeWithoutArgs([&]() {
|
||||
api.CallFenceOnCompletionCallback(apiFence, WGPUFenceCompletionStatus_Success);
|
||||
}));
|
||||
FlushClient();
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, _))
|
||||
.Times(1);
|
||||
FlushServer();
|
||||
}
|
||||
|
||||
// Check that an error in the on completion callback is forwarded to the client.
|
||||
TEST_F(WireFenceTests, OnCompletionError) {
|
||||
wgpuFenceOnCompletion(fence, 0, ToMockFenceOnCompletion, nullptr);
|
||||
EXPECT_CALL(api, OnFenceOnCompletion(apiFence, 0u, _, _)).WillOnce(InvokeWithoutArgs([&]() {
|
||||
api.CallFenceOnCompletionCallback(apiFence, WGPUFenceCompletionStatus_Error);
|
||||
}));
|
||||
FlushClient();
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Error, _)).Times(1);
|
||||
FlushServer();
|
||||
}
|
||||
|
||||
// Test that registering a callback then wire disconnect calls the callback with
|
||||
// DeviceLost.
|
||||
TEST_F(WireFenceTests, OnCompletionThenDisconnect) {
|
||||
wgpuFenceOnCompletion(fence, 0, ToMockFenceOnCompletion, this);
|
||||
EXPECT_CALL(api, OnFenceOnCompletion(apiFence, 0u, _, _)).WillOnce(InvokeWithoutArgs([&]() {
|
||||
api.CallFenceOnCompletionCallback(apiFence, WGPUFenceCompletionStatus_Success);
|
||||
}));
|
||||
FlushClient();
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_DeviceLost, this))
|
||||
.Times(1);
|
||||
GetWireClient()->Disconnect();
|
||||
}
|
||||
|
||||
// Test that registering a callback after wire disconnect calls the callback with
|
||||
// DeviceLost.
|
||||
TEST_F(WireFenceTests, OnCompletionAfterDisconnect) {
|
||||
GetWireClient()->Disconnect();
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_DeviceLost, this))
|
||||
.Times(1);
|
||||
wgpuFenceOnCompletion(fence, 0, ToMockFenceOnCompletion, this);
|
||||
}
|
||||
|
||||
// Without any flushes, it is valid to wait on a value less than or equal to
|
||||
// the last signaled value
|
||||
TEST_F(WireFenceTests, OnCompletionSynchronousValidationSuccess) {
|
||||
wgpuQueueSignal(queue, fence, 4u);
|
||||
wgpuFenceOnCompletion(fence, 2u, ToMockFenceOnCompletion, 0);
|
||||
wgpuFenceOnCompletion(fence, 3u, ToMockFenceOnCompletion, 0);
|
||||
wgpuFenceOnCompletion(fence, 4u, ToMockFenceOnCompletion, 0);
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Unknown, _))
|
||||
.Times(3);
|
||||
}
|
||||
|
||||
// Check that the fence completed value is initialized
|
||||
TEST_F(WireFenceTests, GetCompletedValueInitialization) {
|
||||
EXPECT_EQ(wgpuFenceGetCompletedValue(fence), 1u);
|
||||
}
|
||||
|
||||
// Check that the fence completed value updates after signaling the fence
|
||||
TEST_F(WireFenceTests, GetCompletedValueUpdate) {
|
||||
DoQueueSignal(3u);
|
||||
FlushClient();
|
||||
FlushServer();
|
||||
|
||||
EXPECT_EQ(wgpuFenceGetCompletedValue(fence), 3u);
|
||||
}
|
||||
|
||||
// Check that the fence completed value updates after signaling the fence
|
||||
TEST_F(WireFenceTests, GetCompletedValueUpdateInCallback) {
|
||||
// Signal the fence
|
||||
DoQueueSignal(3u);
|
||||
|
||||
// Register the callback
|
||||
wgpuFenceOnCompletion(fence, 3u, ToMockFenceOnCompletion, this);
|
||||
EXPECT_CALL(api, OnFenceOnCompletion(apiFence, 3u, _, _))
|
||||
.WillOnce(InvokeWithoutArgs([&]() {
|
||||
api.CallFenceOnCompletionCallback(apiFence, WGPUFenceCompletionStatus_Success);
|
||||
}))
|
||||
.RetiresOnSaturation();
|
||||
|
||||
FlushClient();
|
||||
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Success, this))
|
||||
.WillOnce(InvokeWithoutArgs([&]() { EXPECT_EQ(wgpuFenceGetCompletedValue(fence), 3u); }));
|
||||
FlushServer();
|
||||
}
|
||||
|
||||
// Check that the fence completed value does not update without a flush
|
||||
TEST_F(WireFenceTests, GetCompletedValueNoUpdate) {
|
||||
wgpuQueueSignal(queue, fence, 3u);
|
||||
EXPECT_EQ(wgpuFenceGetCompletedValue(fence), 1u);
|
||||
}
|
||||
|
||||
// Check that the callback is called with UNKNOWN when the fence is destroyed
|
||||
// before the completed value is updated
|
||||
TEST_F(WireFenceTests, DestroyBeforeOnCompletionEnd) {
|
||||
wgpuQueueSignal(queue, fence, 3u);
|
||||
wgpuFenceOnCompletion(fence, 2u, ToMockFenceOnCompletion, nullptr);
|
||||
EXPECT_CALL(*mockFenceOnCompletionCallback, Call(WGPUFenceCompletionStatus_Unknown, _))
|
||||
.Times(1);
|
||||
}
|
||||
|
||||
// Test that signaling a fence on a wrong queue is invalid
|
||||
// DISABLED until we have support for multiple queues.
|
||||
TEST_F(WireFenceTests, DISABLED_SignalWrongQueue) {
|
||||
WGPUQueue queue2 = wgpuDeviceGetQueue(device);
|
||||
WGPUQueue apiQueue2 = api.GetNewQueue();
|
||||
EXPECT_CALL(api, DeviceGetQueue(apiDevice)).WillOnce(Return(apiQueue2));
|
||||
FlushClient();
|
||||
|
||||
wgpuQueueSignal(queue2, fence, 2u); // error
|
||||
EXPECT_CALL(api, DeviceInjectError(apiDevice, WGPUErrorType_Validation, ValidStringMessage()))
|
||||
.Times(1);
|
||||
FlushClient();
|
||||
}
|
||||
|
||||
// Test that signaling a fence on a wrong queue does not update fence signaled value
|
||||
// DISABLED until we have support for multiple queues.
|
||||
TEST_F(WireFenceTests, DISABLED_SignalWrongQueueDoesNotUpdateValue) {
|
||||
WGPUQueue queue2 = wgpuDeviceGetQueue(device);
|
||||
WGPUQueue apiQueue2 = api.GetNewQueue();
|
||||
EXPECT_CALL(api, DeviceGetQueue(apiDevice)).WillOnce(Return(apiQueue2));
|
||||
FlushClient();
|
||||
|
||||
wgpuQueueSignal(queue2, fence, 2u); // error
|
||||
EXPECT_CALL(api, DeviceInjectError(apiDevice, WGPUErrorType_Validation, ValidStringMessage()))
|
||||
.Times(1);
|
||||
FlushClient();
|
||||
|
||||
// Fence value should be unchanged.
|
||||
FlushClient();
|
||||
FlushServer();
|
||||
EXPECT_EQ(wgpuFenceGetCompletedValue(fence), 1u);
|
||||
|
||||
// Signaling with 2 on the correct queue should succeed
|
||||
DoQueueSignal(2u); // success
|
||||
FlushClient();
|
||||
FlushServer();
|
||||
EXPECT_EQ(wgpuFenceGetCompletedValue(fence), 2u);
|
||||
}
|
||||
Reference in New Issue
Block a user