• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 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 <gtest/gtest.h>
16 
17 #include "dawn/dawn_proc.h"
18 #include "dawn_native/Instance.h"
19 #include "dawn_native/null/DeviceNull.h"
20 #include "dawn_wire/WireClient.h"
21 #include "utils/TerribleCommandBuffer.h"
22 
23 namespace {
24 
25     // dawn_wire and dawn_native contain duplicated code for the handling of GetProcAddress
26     // so we run the tests against both implementations. This enum is used as a test parameters to
27     // know which implementation to test.
28     enum class DawnFlavor {
29         Native,
30         Wire,
31     };
32 
operator <<(std::ostream & stream,DawnFlavor flavor)33     std::ostream& operator<<(std::ostream& stream, DawnFlavor flavor) {
34         switch (flavor) {
35             case DawnFlavor::Native:
36                 stream << "dawn_native";
37                 break;
38 
39             case DawnFlavor::Wire:
40                 stream << "dawn_wire";
41                 break;
42 
43             default:
44                 UNREACHABLE();
45                 break;
46         }
47         return stream;
48     }
49 
50     class GetProcAddressTests : public testing::TestWithParam<DawnFlavor> {
51       public:
GetProcAddressTests()52         GetProcAddressTests()
53             : testing::TestWithParam<DawnFlavor>(),
54               mNativeInstance(dawn_native::InstanceBase::Create()),
55               mNativeAdapter(mNativeInstance.Get()) {
56         }
57 
SetUp()58         void SetUp() override {
59             switch (GetParam()) {
60                 case DawnFlavor::Native: {
61                     mDevice = wgpu::Device::Acquire(
62                         reinterpret_cast<WGPUDevice>(mNativeAdapter.CreateDevice(nullptr)));
63                     mProcs = dawn_native::GetProcs();
64                     break;
65                 }
66 
67                 case DawnFlavor::Wire: {
68                     mC2sBuf = std::make_unique<utils::TerribleCommandBuffer>();
69 
70                     dawn_wire::WireClientDescriptor clientDesc = {};
71                     clientDesc.serializer = mC2sBuf.get();
72                     mWireClient = std::make_unique<dawn_wire::WireClient>(clientDesc);
73 
74                     mDevice = wgpu::Device::Acquire(mWireClient->ReserveDevice().device);
75                     mProcs = dawn_wire::client::GetProcs();
76                     break;
77                 }
78 
79                 default:
80                     UNREACHABLE();
81                     break;
82             }
83 
84             dawnProcSetProcs(&mProcs);
85         }
86 
TearDown()87         void TearDown() override {
88             // Destroy the device before freeing the instance or the wire client in the destructor
89             mDevice = wgpu::Device();
90         }
91 
92       protected:
93         Ref<dawn_native::InstanceBase> mNativeInstance;
94         dawn_native::null::Adapter mNativeAdapter;
95 
96         std::unique_ptr<utils::TerribleCommandBuffer> mC2sBuf;
97         std::unique_ptr<dawn_wire::WireClient> mWireClient;
98 
99         wgpu::Device mDevice;
100         DawnProcTable mProcs;
101     };
102 
103     // Test GetProcAddress with and without devices on some valid examples
TEST_P(GetProcAddressTests,ValidExamples)104     TEST_P(GetProcAddressTests, ValidExamples) {
105         ASSERT_EQ(mProcs.getProcAddress(nullptr, "wgpuDeviceCreateBuffer"),
106                   reinterpret_cast<WGPUProc>(mProcs.deviceCreateBuffer));
107         ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), "wgpuDeviceCreateBuffer"),
108                   reinterpret_cast<WGPUProc>(mProcs.deviceCreateBuffer));
109         ASSERT_EQ(mProcs.getProcAddress(nullptr, "wgpuQueueSubmit"),
110                   reinterpret_cast<WGPUProc>(mProcs.queueSubmit));
111         ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), "wgpuQueueSubmit"),
112                   reinterpret_cast<WGPUProc>(mProcs.queueSubmit));
113     }
114 
115     // Test GetProcAddress with and without devices on nullptr procName
TEST_P(GetProcAddressTests,Nullptr)116     TEST_P(GetProcAddressTests, Nullptr) {
117         ASSERT_EQ(mProcs.getProcAddress(nullptr, nullptr), nullptr);
118         ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), nullptr), nullptr);
119     }
120 
121     // Test GetProcAddress with and without devices on some invalid
TEST_P(GetProcAddressTests,InvalidExamples)122     TEST_P(GetProcAddressTests, InvalidExamples) {
123         ASSERT_EQ(mProcs.getProcAddress(nullptr, "wgpuDeviceDoSomething"), nullptr);
124         ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), "wgpuDeviceDoSomething"), nullptr);
125 
126         // Trigger the condition where lower_bound will return the end of the procMap.
127         ASSERT_EQ(mProcs.getProcAddress(nullptr, "zzzzzzz"), nullptr);
128         ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), "zzzzzzz"), nullptr);
129         ASSERT_EQ(mProcs.getProcAddress(nullptr, "ZZ"), nullptr);
130         ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), "ZZ"), nullptr);
131 
132         // Some more potential corner cases.
133         ASSERT_EQ(mProcs.getProcAddress(nullptr, ""), nullptr);
134         ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), ""), nullptr);
135         ASSERT_EQ(mProcs.getProcAddress(nullptr, "0"), nullptr);
136         ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), "0"), nullptr);
137     }
138 
139     // Test that GetProcAddress supports freestanding function that are handled specially
TEST_P(GetProcAddressTests,FreeStandingFunctions)140     TEST_P(GetProcAddressTests, FreeStandingFunctions) {
141         ASSERT_EQ(mProcs.getProcAddress(nullptr, "wgpuGetProcAddress"),
142                   reinterpret_cast<WGPUProc>(mProcs.getProcAddress));
143         ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), "wgpuGetProcAddress"),
144                   reinterpret_cast<WGPUProc>(mProcs.getProcAddress));
145 
146         ASSERT_EQ(mProcs.getProcAddress(nullptr, "wgpuCreateInstance"),
147                   reinterpret_cast<WGPUProc>(mProcs.createInstance));
148         ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), "wgpuCreateInstance"),
149                   reinterpret_cast<WGPUProc>(mProcs.createInstance));
150     }
151 
152     INSTANTIATE_TEST_SUITE_P(,
153                              GetProcAddressTests,
154                              testing::Values(DawnFlavor::Native, DawnFlavor::Wire),
155                              testing::PrintToStringParamName());
156 
TEST(GetProcAddressInternalTests,CheckDawnNativeProcMapOrder)157     TEST(GetProcAddressInternalTests, CheckDawnNativeProcMapOrder) {
158         std::vector<const char*> names = dawn_native::GetProcMapNamesForTesting();
159         for (size_t i = 1; i < names.size(); i++) {
160             ASSERT_LT(std::string(names[i - 1]), std::string(names[i]));
161         }
162     }
163 
TEST(GetProcAddressInternalTests,CheckDawnWireClientProcMapOrder)164     TEST(GetProcAddressInternalTests, CheckDawnWireClientProcMapOrder) {
165         std::vector<const char*> names = dawn_wire::client::GetProcMapNamesForTesting();
166         for (size_t i = 1; i < names.size(); i++) {
167             ASSERT_LT(std::string(names[i - 1]), std::string(names[i]));
168         }
169     }
170 }  // anonymous namespace
171