1 // Copyright 2020 The Dawn Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <gmock/gmock.h>
16 #include "tests/DawnTest.h"
17
18 using namespace testing;
19
20 class MockMapCallback {
21 public:
22 MOCK_METHOD(void, Call, (WGPUBufferMapAsyncStatus status, void* userdata));
23 };
24
25 static std::unique_ptr<MockMapCallback> mockMapCallback;
ToMockMapCallback(WGPUBufferMapAsyncStatus status,void * userdata)26 static void ToMockMapCallback(WGPUBufferMapAsyncStatus status, void* userdata) {
27 EXPECT_EQ(status, WGPUBufferMapAsyncStatus_Success);
28 mockMapCallback->Call(status, userdata);
29 }
30
31 class MockQueueWorkDoneCallback {
32 public:
33 MOCK_METHOD(void, Call, (WGPUQueueWorkDoneStatus status, void* userdata));
34 };
35
36 static std::unique_ptr<MockQueueWorkDoneCallback> mockQueueWorkDoneCallback;
ToMockQueueWorkDone(WGPUQueueWorkDoneStatus status,void * userdata)37 static void ToMockQueueWorkDone(WGPUQueueWorkDoneStatus status, void* userdata) {
38 mockQueueWorkDoneCallback->Call(status, userdata);
39 }
40
41 class QueueTimelineTests : public DawnTest {
42 protected:
SetUp()43 void SetUp() override {
44 DawnTest::SetUp();
45
46 mockMapCallback = std::make_unique<MockMapCallback>();
47 mockQueueWorkDoneCallback = std::make_unique<MockQueueWorkDoneCallback>();
48
49 wgpu::BufferDescriptor descriptor;
50 descriptor.size = 4;
51 descriptor.usage = wgpu::BufferUsage::MapRead;
52 mMapReadBuffer = device.CreateBuffer(&descriptor);
53 }
54
TearDown()55 void TearDown() override {
56 mockMapCallback = nullptr;
57 mockQueueWorkDoneCallback = nullptr;
58 DawnTest::TearDown();
59 }
60
61 wgpu::Buffer mMapReadBuffer;
62 };
63
64 // Test that mMapReadBuffer.MapAsync callback happens before queue.OnWorkDone callback
65 // when queue.OnSubmittedWorkDone is called after mMapReadBuffer.MapAsync. The callback order should
66 // happen in the order the functions are called.
TEST_P(QueueTimelineTests,MapRead_OnWorkDone)67 TEST_P(QueueTimelineTests, MapRead_OnWorkDone) {
68 testing::InSequence sequence;
69 EXPECT_CALL(*mockMapCallback, Call(WGPUBufferMapAsyncStatus_Success, this)).Times(1);
70 EXPECT_CALL(*mockQueueWorkDoneCallback, Call(WGPUQueueWorkDoneStatus_Success, this)).Times(1);
71
72 mMapReadBuffer.MapAsync(wgpu::MapMode::Read, 0, wgpu::kWholeMapSize, ToMockMapCallback, this);
73
74 queue.OnSubmittedWorkDone(0u, ToMockQueueWorkDone, this);
75
76 WaitForAllOperations();
77 mMapReadBuffer.Unmap();
78 }
79
80 // Test that queue.OnWorkDone callback happens before mMapReadBuffer.MapAsync callback when
81 // queue.Signal is called before mMapReadBuffer.MapAsync. The callback order should
82 // happen in the order the functions are called.
TEST_P(QueueTimelineTests,OnWorkDone_MapRead)83 TEST_P(QueueTimelineTests, OnWorkDone_MapRead) {
84 testing::InSequence sequence;
85 EXPECT_CALL(*mockQueueWorkDoneCallback, Call(WGPUQueueWorkDoneStatus_Success, this)).Times(1);
86 EXPECT_CALL(*mockMapCallback, Call(WGPUBufferMapAsyncStatus_Success, this)).Times(1);
87
88 queue.OnSubmittedWorkDone(0u, ToMockQueueWorkDone, this);
89
90 mMapReadBuffer.MapAsync(wgpu::MapMode::Read, 0, wgpu::kWholeMapSize, ToMockMapCallback, this);
91
92 WaitForAllOperations();
93 mMapReadBuffer.Unmap();
94 }
95
96 DAWN_INSTANTIATE_TEST(QueueTimelineTests,
97 D3D12Backend(),
98 MetalBackend(),
99 OpenGLBackend(),
100 OpenGLESBackend(),
101 VulkanBackend());
102