blob: f10b802e454251b9d0d0cde191f4259d641c5b89 [file] [log] [blame]
Corentin Wallez4a9ef4e2018-07-18 11:40:26 +02001// Copyright 2017 The Dawn Authors
Corentin Wallezeaae7462017-06-16 18:34:35 -04002//
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
Austin Engca0eac32019-08-28 23:18:10 +000015#ifndef TESTS_DAWNTEST_H_
16#define TESTS_DAWNTEST_H_
17
Corentin Wallez95586ff2019-12-05 11:13:01 +000018#include "common/Log.h"
Corentin Wallez96496822019-10-15 11:44:38 +000019#include "dawn/dawn_proc_table.h"
Corentin Wallezcab352c2019-10-28 13:27:36 +000020#include "dawn/webgpu_cpp.h"
Jiawei Shao58809d42018-09-19 00:32:52 +000021#include "dawn_native/DawnNative.h"
Ryan Harrisonacdc35d2021-04-14 14:55:07 +000022#include "tests/ToggleParser.h"
Corentin Wallezeaae7462017-06-16 18:34:35 -040023
Bryan Bernhart41b3f9c2020-11-20 20:38:37 +000024#include <dawn_platform/DawnPlatform.h>
Corentin Wallezeaae7462017-06-16 18:34:35 -040025#include <gtest/gtest.h>
Jiawei Shao15d4c2e2019-04-26 07:52:57 +000026
Austin Eng4234c392017-07-17 09:37:08 -040027#include <memory>
Corentin Wallez0b2f5522019-02-21 16:29:12 +000028#include <unordered_map>
Jiawei Shao93373ab2019-05-29 00:07:37 +000029#include <vector>
Corentin Wallezeaae7462017-06-16 18:34:35 -040030
Corentin Wallez9fc65342018-07-18 15:28:38 +020031// Getting data back from Dawn is done in an async manners so all expectations are "deferred"
Corentin Wallezeaae7462017-06-16 18:34:35 -040032// until the end of the test. Also expectations use a copy to a MapRead buffer to get the data
Corentin Wallezec053552019-07-08 10:05:46 +000033// so resources should have the CopySrc allowed usage bit if you want to add expectations on
Corentin Walleza4da0322018-07-18 15:18:25 +020034// them.
Xinghua Caodb8f8042020-06-08 12:18:21 +000035
Hao Lic0acb252020-08-04 06:41:56 +000036#define EXPECT_BUFFER(buffer, offset, size, expectation) \
37 AddBufferExpectation(__FILE__, __LINE__, buffer, offset, size, expectation)
Xinghua Caodb8f8042020-06-08 12:18:21 +000038
Hao Lic0acb252020-08-04 06:41:56 +000039#define EXPECT_BUFFER_U16_EQ(expected, buffer, offset) \
40 EXPECT_BUFFER(buffer, offset, sizeof(uint16_t), new ::detail::ExpectEq<uint16_t>(expected))
Corentin Wallezeaae7462017-06-16 18:34:35 -040041
Hao Lic0acb252020-08-04 06:41:56 +000042#define EXPECT_BUFFER_U16_RANGE_EQ(expected, buffer, offset, count) \
43 EXPECT_BUFFER(buffer, offset, sizeof(uint16_t) * (count), \
44 new ::detail::ExpectEq<uint16_t>(expected, count))
Austin Eng49fe5662017-07-04 10:53:42 -040045
Hao Lic0acb252020-08-04 06:41:56 +000046#define EXPECT_BUFFER_U32_EQ(expected, buffer, offset) \
47 EXPECT_BUFFER(buffer, offset, sizeof(uint32_t), new ::detail::ExpectEq<uint32_t>(expected))
Austin Eng8f9523e2020-06-19 16:21:33 +000048
Hao Lic0acb252020-08-04 06:41:56 +000049#define EXPECT_BUFFER_U32_RANGE_EQ(expected, buffer, offset, count) \
50 EXPECT_BUFFER(buffer, offset, sizeof(uint32_t) * (count), \
51 new ::detail::ExpectEq<uint32_t>(expected, count))
52
Hao Li9ff83f62021-01-12 01:44:01 +000053#define EXPECT_BUFFER_U64_EQ(expected, buffer, offset) \
54 EXPECT_BUFFER(buffer, offset, sizeof(uint64_t), new ::detail::ExpectEq<uint64_t>(expected))
55
Hao Lic0acb252020-08-04 06:41:56 +000056#define EXPECT_BUFFER_U64_RANGE_EQ(expected, buffer, offset, count) \
57 EXPECT_BUFFER(buffer, offset, sizeof(uint64_t) * (count), \
58 new ::detail::ExpectEq<uint64_t>(expected, count))
59
60#define EXPECT_BUFFER_FLOAT_EQ(expected, buffer, offset) \
61 EXPECT_BUFFER(buffer, offset, sizeof(float), new ::detail::ExpectEq<float>(expected))
62
63#define EXPECT_BUFFER_FLOAT_RANGE_EQ(expected, buffer, offset, count) \
64 EXPECT_BUFFER(buffer, offset, sizeof(float) * (count), \
65 new ::detail::ExpectEq<float>(expected, count))
Austin Eng8f9523e2020-06-19 16:21:33 +000066
Corentin Wallez4cd65f02017-06-27 00:11:16 -040067// Test a pixel of the mip level 0 of a 2D texture.
Austin Eng0a434272020-08-04 19:46:37 +000068#define EXPECT_PIXEL_RGBA8_EQ(expected, texture, x, y) \
Yunchao He4eb40c12021-03-31 22:15:53 +000069 AddTextureExpectation(__FILE__, __LINE__, expected, texture, {x, y})
Austin Enge5bd3e02017-07-17 16:16:50 -040070
Austin Eng0a434272020-08-04 19:46:37 +000071#define EXPECT_PIXEL_FLOAT_EQ(expected, texture, x, y) \
Yunchao He4eb40c12021-03-31 22:15:53 +000072 AddTextureExpectation(__FILE__, __LINE__, expected, texture, {x, y})
Austin Eng0d661982020-01-16 00:12:10 +000073
shrekshaof8c5e4a2020-12-24 03:11:17 +000074#define EXPECT_PIXEL_RGBA8_BETWEEN(color0, color1, texture, x, y) \
75 AddTextureBetweenColorsExpectation(__FILE__, __LINE__, color0, color1, texture, x, y)
76
Austin Eng0a434272020-08-04 19:46:37 +000077// TODO(enga): Migrate other texure expectation helpers to this common one.
78#define EXPECT_TEXTURE_EQ(...) AddTextureExpectation(__FILE__, __LINE__, __VA_ARGS__)
Austin Eng0d661982020-01-16 00:12:10 +000079
Corentin Wallez2dfb3f02019-02-28 09:45:48 +000080// Should only be used to test validation of function that can't be tested by regular validation
81// tests;
Austin Eng3aa5be92020-04-16 21:36:33 +000082#define ASSERT_DEVICE_ERROR(statement) \
83 StartExpectDeviceError(); \
84 statement; \
85 FlushWire(); \
86 if (!EndExpectDeviceError()) { \
87 FAIL() << "Expected device error in:\n " << #statement; \
88 } \
89 do { \
90 } while (0)
Corentin Wallez2dfb3f02019-02-28 09:45:48 +000091
Corentin Wallez4cd65f02017-06-27 00:11:16 -040092struct RGBA8 {
Corentin Walleza4da0322018-07-18 15:18:25 +020093 constexpr RGBA8() : RGBA8(0, 0, 0, 0) {
94 }
95 constexpr RGBA8(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : r(r), g(g), b(b), a(a) {
Corentin Wallez4cd65f02017-06-27 00:11:16 -040096 }
97 bool operator==(const RGBA8& other) const;
98 bool operator!=(const RGBA8& other) const;
shrekshaof8c5e4a2020-12-24 03:11:17 +000099 bool operator<=(const RGBA8& other) const;
100 bool operator>=(const RGBA8& other) const;
Corentin Wallez4cd65f02017-06-27 00:11:16 -0400101
102 uint8_t r, g, b, a;
Yunchao He0c02f542019-11-19 17:57:30 +0000103
104 static const RGBA8 kZero;
105 static const RGBA8 kBlack;
106 static const RGBA8 kRed;
107 static const RGBA8 kGreen;
108 static const RGBA8 kBlue;
109 static const RGBA8 kYellow;
110 static const RGBA8 kWhite;
Corentin Wallez4cd65f02017-06-27 00:11:16 -0400111};
Corentin Walleza4da0322018-07-18 15:18:25 +0200112std::ostream& operator<<(std::ostream& stream, const RGBA8& color);
Corentin Wallez4cd65f02017-06-27 00:11:16 -0400113
Austin Engda722ad2020-05-15 20:28:05 +0000114struct BackendTestConfig {
115 BackendTestConfig(wgpu::BackendType backendType,
116 std::initializer_list<const char*> forceEnabledWorkarounds = {},
117 std::initializer_list<const char*> forceDisabledWorkarounds = {});
118
119 wgpu::BackendType backendType;
120
121 std::vector<const char*> forceEnabledWorkarounds;
122 std::vector<const char*> forceDisabledWorkarounds;
123};
124
Austin Eng25c747c2020-05-15 16:07:12 +0000125struct TestAdapterProperties : wgpu::AdapterProperties {
126 TestAdapterProperties(const wgpu::AdapterProperties& properties, bool selected);
127 std::string adapterName;
128 bool selected;
129
130 private:
131 // This may be temporary, so it is copied into |adapterName| and made private.
132 using wgpu::AdapterProperties::name;
133};
134
Austin Engda722ad2020-05-15 20:28:05 +0000135struct AdapterTestParam {
136 AdapterTestParam(const BackendTestConfig& config,
137 const TestAdapterProperties& adapterProperties);
Jiawei Shao15d4c2e2019-04-26 07:52:57 +0000138
Austin Engda722ad2020-05-15 20:28:05 +0000139 TestAdapterProperties adapterProperties;
Jiawei Shao93373ab2019-05-29 00:07:37 +0000140 std::vector<const char*> forceEnabledWorkarounds;
Natasha Lee28232ce2019-06-11 18:11:05 +0000141 std::vector<const char*> forceDisabledWorkarounds;
Jiawei Shao15d4c2e2019-04-26 07:52:57 +0000142};
143
Austin Engda722ad2020-05-15 20:28:05 +0000144std::ostream& operator<<(std::ostream& os, const AdapterTestParam& param);
Brian Hoe25a3ae2019-08-27 01:44:29 +0000145
Austin Engda722ad2020-05-15 20:28:05 +0000146BackendTestConfig D3D12Backend(std::initializer_list<const char*> forceEnabledWorkarounds = {},
147 std::initializer_list<const char*> forceDisabledWorkarounds = {});
Corentin Wallezeaae7462017-06-16 18:34:35 -0400148
Austin Engda722ad2020-05-15 20:28:05 +0000149BackendTestConfig MetalBackend(std::initializer_list<const char*> forceEnabledWorkarounds = {},
150 std::initializer_list<const char*> forceDisabledWorkarounds = {});
Austin Eng6c1d6462020-02-25 16:23:17 +0000151
Austin Engda722ad2020-05-15 20:28:05 +0000152BackendTestConfig NullBackend(std::initializer_list<const char*> forceEnabledWorkarounds = {},
153 std::initializer_list<const char*> forceDisabledWorkarounds = {});
Corentin Wallez11652ff2020-03-20 17:07:20 +0000154
Austin Engda722ad2020-05-15 20:28:05 +0000155BackendTestConfig OpenGLBackend(std::initializer_list<const char*> forceEnabledWorkarounds = {},
156 std::initializer_list<const char*> forceDisabledWorkarounds = {});
Austin Eng6c1d6462020-02-25 16:23:17 +0000157
Stephen Whited45ab072020-11-25 16:45:04 +0000158BackendTestConfig OpenGLESBackend(std::initializer_list<const char*> forceEnabledWorkarounds = {},
159 std::initializer_list<const char*> forceDisabledWorkarounds = {});
160
Austin Engda722ad2020-05-15 20:28:05 +0000161BackendTestConfig VulkanBackend(std::initializer_list<const char*> forceEnabledWorkarounds = {},
162 std::initializer_list<const char*> forceDisabledWorkarounds = {});
Austin Eng6c1d6462020-02-25 16:23:17 +0000163
Stephen Whited45ab072020-11-25 16:45:04 +0000164struct GLFWwindow;
165
Corentin Wallezeaae7462017-06-16 18:34:35 -0400166namespace utils {
Austin Engf5800962020-08-14 21:02:12 +0000167 class PlatformDebugLogger;
Corentin Wallezbdc86772018-07-26 15:07:57 +0200168 class TerribleCommandBuffer;
Austin Enge58d5a32021-01-27 22:54:04 +0000169 class WireHelper;
Jiawei Shao93373ab2019-05-29 00:07:37 +0000170} // namespace utils
Corentin Wallezeaae7462017-06-16 18:34:35 -0400171
172namespace detail {
173 class Expectation;
Austin Eng0a434272020-08-04 19:46:37 +0000174
175 template <typename T>
176 class ExpectEq;
shrekshaof8c5e4a2020-12-24 03:11:17 +0000177 template <typename T>
178 class ExpectBetweenColors;
Jiawei Shao93373ab2019-05-29 00:07:37 +0000179} // namespace detail
Corentin Wallezeaae7462017-06-16 18:34:35 -0400180
Corentin Wallezbdc86772018-07-26 15:07:57 +0200181namespace dawn_wire {
Austin Engcbc206e2019-12-10 23:32:48 +0000182 class CommandHandler;
Austin Enge2c85132019-02-11 21:50:16 +0000183 class WireClient;
184 class WireServer;
Corentin Wallezbdc86772018-07-26 15:07:57 +0200185} // namespace dawn_wire
Corentin Wallez419e9842018-06-07 13:10:44 +0200186
Corentin Wallez0b2f5522019-02-21 16:29:12 +0000187void InitDawnEnd2EndTestEnvironment(int argc, char** argv);
188
189class DawnTestEnvironment : public testing::Environment {
190 public:
191 DawnTestEnvironment(int argc, char** argv);
Austin Engf5800962020-08-14 21:02:12 +0000192 ~DawnTestEnvironment() override;
Corentin Wallez0b2f5522019-02-21 16:29:12 +0000193
Austin Engca0eac32019-08-28 23:18:10 +0000194 static void SetEnvironment(DawnTestEnvironment* env);
195
Austin Engda722ad2020-05-15 20:28:05 +0000196 std::vector<AdapterTestParam> GetAvailableAdapterTestParamsForBackends(
197 const BackendTestConfig* params,
198 size_t numParams);
Austin Eng25c747c2020-05-15 16:07:12 +0000199
Corentin Wallez0b2f5522019-02-21 16:29:12 +0000200 void SetUp() override;
Jiajie Hu9e5b9ed2019-11-20 09:45:41 +0000201 void TearDown() override;
Corentin Wallez0b2f5522019-02-21 16:29:12 +0000202
Corentin Wallez0ee98592019-05-01 12:57:27 +0000203 bool UsesWire() const;
Brandon Jonesbdbf98a2021-02-04 19:32:12 +0000204 dawn_native::BackendValidationLevel GetBackendValidationLevel() const;
Corentin Wallez0b2f5522019-02-21 16:29:12 +0000205 dawn_native::Instance* GetInstance() const;
Li, Hao35716c22019-07-08 03:25:54 +0000206 bool HasVendorIdFilter() const;
207 uint32_t GetVendorIdFilter() const;
Stephen Whiteeb71aaf2021-02-17 17:07:08 +0000208 bool HasBackendTypeFilter() const;
209 wgpu::BackendType GetBackendTypeFilter() const;
Austin Engcbc206e2019-12-10 23:32:48 +0000210 const char* GetWireTraceDir() const;
Stephen Whited45ab072020-11-25 16:45:04 +0000211 GLFWwindow* GetOpenGLWindow() const;
212 GLFWwindow* GetOpenGLESWindow() const;
Corentin Wallez0b2f5522019-02-21 16:29:12 +0000213
Austin Engb38a9c32020-11-14 01:09:23 +0000214 const std::vector<std::string>& GetEnabledToggles() const;
215 const std::vector<std::string>& GetDisabledToggles() const;
216
Austin Eng92a011a2019-10-17 19:00:32 +0000217 protected:
218 std::unique_ptr<dawn_native::Instance> mInstance;
219
Corentin Wallez0b2f5522019-02-21 16:29:12 +0000220 private:
Austin Eng25c747c2020-05-15 16:07:12 +0000221 void ParseArgs(int argc, char** argv);
Stephen Whited45ab072020-11-25 16:45:04 +0000222 std::unique_ptr<dawn_native::Instance> CreateInstanceAndDiscoverAdapters();
Austin Engda722ad2020-05-15 20:28:05 +0000223 void SelectPreferredAdapterProperties(const dawn_native::Instance* instance);
Austin Engb38a9c32020-11-14 01:09:23 +0000224 void PrintTestConfigurationAndAdapterInfo(dawn_native::Instance* instance) const;
Corentin Wallez0b2f5522019-02-21 16:29:12 +0000225
226 bool mUseWire = false;
Brandon Jonesbdbf98a2021-02-04 19:32:12 +0000227 dawn_native::BackendValidationLevel mBackendValidationLevel =
228 dawn_native::BackendValidationLevel::Disabled;
Rafael Cintron4729b152019-06-21 02:09:05 +0000229 bool mBeginCaptureOnStartup = false;
Li, Hao35716c22019-07-08 03:25:54 +0000230 bool mHasVendorIdFilter = false;
231 uint32_t mVendorIdFilter = 0;
Stephen Whiteeb71aaf2021-02-17 17:07:08 +0000232 bool mHasBackendTypeFilter = false;
233 wgpu::BackendType mBackendTypeFilter;
Austin Engcbc206e2019-12-10 23:32:48 +0000234 std::string mWireTraceDir;
Austin Engb38a9c32020-11-14 01:09:23 +0000235
Ryan Harrisonacdc35d2021-04-14 14:55:07 +0000236 ToggleParser mToggleParser;
237
Austin Engda722ad2020-05-15 20:28:05 +0000238 std::vector<dawn_native::DeviceType> mDevicePreferences;
Austin Eng25c747c2020-05-15 16:07:12 +0000239 std::vector<TestAdapterProperties> mAdapterProperties;
Austin Engf5800962020-08-14 21:02:12 +0000240
241 std::unique_ptr<utils::PlatformDebugLogger> mPlatformDebugLogger;
Stephen Whited45ab072020-11-25 16:45:04 +0000242 GLFWwindow* mOpenGLWindow;
243 GLFWwindow* mOpenGLESWindow;
Corentin Wallez0b2f5522019-02-21 16:29:12 +0000244};
245
Austin Engca0eac32019-08-28 23:18:10 +0000246class DawnTestBase {
247 friend class DawnPerfTestBase;
Corentin Wallezeaae7462017-06-16 18:34:35 -0400248
Austin Engca0eac32019-08-28 23:18:10 +0000249 public:
Austin Engda722ad2020-05-15 20:28:05 +0000250 DawnTestBase(const AdapterTestParam& param);
Austin Engca0eac32019-08-28 23:18:10 +0000251 virtual ~DawnTestBase();
252
253 void SetUp();
254 void TearDown();
Corentin Wallez134e0802017-07-17 17:13:57 -0400255
Corentin Wallez419e9842018-06-07 13:10:44 +0200256 bool IsD3D12() const;
257 bool IsMetal() const;
Corentin Wallez11652ff2020-03-20 17:07:20 +0000258 bool IsNull() const;
Corentin Wallez419e9842018-06-07 13:10:44 +0200259 bool IsOpenGL() const;
Stephen Whited45ab072020-11-25 16:45:04 +0000260 bool IsOpenGLES() const;
Corentin Wallez419e9842018-06-07 13:10:44 +0200261 bool IsVulkan() const;
Corentin Wallezeaae7462017-06-16 18:34:35 -0400262
Jiawei Shao58809d42018-09-19 00:32:52 +0000263 bool IsAMD() const;
264 bool IsARM() const;
265 bool IsImgTec() const;
266 bool IsIntel() const;
267 bool IsNvidia() const;
268 bool IsQualcomm() const;
Corentin Wallezd56b69f2020-04-09 08:16:30 +0000269 bool IsSwiftshader() const;
Stephen Whitef09a6702021-01-18 17:47:07 +0000270 bool IsANGLE() const;
Bryan Bernhart8c255ac2020-07-10 22:58:48 +0000271 bool IsWARP() const;
Jiawei Shao58809d42018-09-19 00:32:52 +0000272
273 bool IsWindows() const;
274 bool IsLinux() const;
275 bool IsMacOS() const;
276
Corentin Wallez0ee98592019-05-01 12:57:27 +0000277 bool UsesWire() const;
Li, Hao6fa398e2019-06-25 00:49:56 +0000278 bool IsBackendValidationEnabled() const;
Corentin Wallez0ee98592019-05-01 12:57:27 +0000279
Austin Eng0e9e5ee2020-06-19 17:35:33 +0000280 bool IsAsan() const;
281
Enrico Galli2b6b0f42020-11-05 18:52:49 +0000282 bool HasToggleEnabled(const char* workaround) const;
283
Corentin Wallez2dfb3f02019-02-28 09:45:48 +0000284 void StartExpectDeviceError();
285 bool EndExpectDeviceError();
286
Li, Hao35716c22019-07-08 03:25:54 +0000287 bool HasVendorIdFilter() const;
288 uint32_t GetVendorIdFilter() const;
289
Stephen Whiteeb71aaf2021-02-17 17:07:08 +0000290 bool HasBackendTypeFilter() const;
291 wgpu::BackendType GetBackendTypeFilter() const;
292
Corentin Wallez11652ff2020-03-20 17:07:20 +0000293 wgpu::Instance GetInstance() const;
294 dawn_native::Adapter GetAdapter() const;
295
Bryan Bernhart41b3f9c2020-11-20 20:38:37 +0000296 virtual std::unique_ptr<dawn_platform::Platform> CreateTestPlatform();
297
Corentin Wallez419e9842018-06-07 13:10:44 +0200298 protected:
Corentin Wallezcab352c2019-10-28 13:27:36 +0000299 wgpu::Device device;
300 wgpu::Queue queue;
Corentin Wallezeaae7462017-06-16 18:34:35 -0400301
Austin Eng8aa036e2019-05-24 22:31:36 +0000302 DawnProcTable backendProcs = {};
Corentin Wallezcab352c2019-10-28 13:27:36 +0000303 WGPUDevice backendDevice = nullptr;
Austin Eng8aa036e2019-05-24 22:31:36 +0000304
Kai Ninomiya2bb80352020-10-28 21:23:45 +0000305 size_t mLastWarningCount = 0;
306
Corentin Wallez419e9842018-06-07 13:10:44 +0200307 // Helper methods to implement the EXPECT_ macros
308 std::ostringstream& AddBufferExpectation(const char* file,
309 int line,
Corentin Wallezcab352c2019-10-28 13:27:36 +0000310 const wgpu::Buffer& buffer,
Austin Engcf52d712019-04-05 20:51:29 +0000311 uint64_t offset,
312 uint64_t size,
Corentin Wallez419e9842018-06-07 13:10:44 +0200313 detail::Expectation* expectation);
Austin Eng0a434272020-08-04 19:46:37 +0000314
315 template <typename T>
Corentin Wallez419e9842018-06-07 13:10:44 +0200316 std::ostringstream& AddTextureExpectation(const char* file,
317 int line,
Austin Eng0a434272020-08-04 19:46:37 +0000318 const T* expectedData,
Corentin Wallezcab352c2019-10-28 13:27:36 +0000319 const wgpu::Texture& texture,
Yunchao He4eb40c12021-03-31 22:15:53 +0000320 wgpu::Origin3D origin,
321 wgpu::Extent3D extent,
Austin Eng0a434272020-08-04 19:46:37 +0000322 uint32_t level = 0,
Austin Eng0a434272020-08-04 19:46:37 +0000323 wgpu::TextureAspect aspect = wgpu::TextureAspect::All,
324 uint32_t bytesPerRow = 0) {
325 return AddTextureExpectationImpl(
Yunchao He4eb40c12021-03-31 22:15:53 +0000326 file, line,
327 new detail::ExpectEq<T>(expectedData,
328 extent.width * extent.height * extent.depthOrArrayLayers),
Yunchao Heff55b2f2021-04-07 16:57:11 +0000329 texture, origin, extent, level, aspect, sizeof(T), bytesPerRow);
Austin Eng0a434272020-08-04 19:46:37 +0000330 }
331
332 template <typename T>
333 std::ostringstream& AddTextureExpectation(const char* file,
334 int line,
335 const T& expectedData,
336 const wgpu::Texture& texture,
Yunchao He4eb40c12021-03-31 22:15:53 +0000337 wgpu::Origin3D origin,
Austin Eng0a434272020-08-04 19:46:37 +0000338 uint32_t level = 0,
Austin Eng0a434272020-08-04 19:46:37 +0000339 wgpu::TextureAspect aspect = wgpu::TextureAspect::All,
340 uint32_t bytesPerRow = 0) {
341 return AddTextureExpectationImpl(file, line, new detail::ExpectEq<T>(expectedData), texture,
Yunchao Heff55b2f2021-04-07 16:57:11 +0000342 origin, {1, 1}, level, aspect, sizeof(T), bytesPerRow);
Austin Eng0a434272020-08-04 19:46:37 +0000343 }
Corentin Wallezeaae7462017-06-16 18:34:35 -0400344
shrekshaof8c5e4a2020-12-24 03:11:17 +0000345 template <typename T>
346 std::ostringstream& AddTextureBetweenColorsExpectation(
347 const char* file,
348 int line,
349 const T& color0,
350 const T& color1,
351 const wgpu::Texture& texture,
352 uint32_t x,
353 uint32_t y,
354 uint32_t level = 0,
shrekshaof8c5e4a2020-12-24 03:11:17 +0000355 wgpu::TextureAspect aspect = wgpu::TextureAspect::All,
356 uint32_t bytesPerRow = 0) {
357 return AddTextureExpectationImpl(
Yunchao He4eb40c12021-03-31 22:15:53 +0000358 file, line, new detail::ExpectBetweenColors<T>(color0, color1), texture, {x, y}, {1, 1},
Yunchao Heff55b2f2021-04-07 16:57:11 +0000359 level, aspect, sizeof(T), bytesPerRow);
shrekshaof8c5e4a2020-12-24 03:11:17 +0000360 }
361
Corentin Wallez419e9842018-06-07 13:10:44 +0200362 void WaitABit();
Corentin Wallezcc141792019-05-01 12:07:37 +0000363 void FlushWire();
Natasha Lee51af1b42020-10-12 22:32:33 +0000364 void WaitForAllOperations();
Kai Ninomiyac16a67a2017-07-27 18:30:57 -0700365
Jiawei Shao574b9512019-08-02 00:06:38 +0000366 bool SupportsExtensions(const std::vector<const char*>& extensions);
367
368 // Called in SetUp() to get the extensions required to be enabled in the tests. The tests must
369 // check if the required extensions are supported by the adapter in this function and guarantee
370 // the returned extensions are all supported by the adapter. The tests may provide different
371 // code path to handle the situation when not all extensions are supported.
372 virtual std::vector<const char*> GetRequiredExtensions();
373
Corentin Wallezf12c9db2020-01-10 13:28:18 +0000374 const wgpu::AdapterProperties& GetAdapterProperties() const;
375
Corentin Wallez419e9842018-06-07 13:10:44 +0200376 private:
Austin Engda722ad2020-05-15 20:28:05 +0000377 AdapterTestParam mParam;
Austin Enge58d5a32021-01-27 22:54:04 +0000378 std::unique_ptr<utils::WireHelper> mWireHelper;
Austin Engcbc206e2019-12-10 23:32:48 +0000379
Corentin Wallez2dfb3f02019-02-28 09:45:48 +0000380 // Tracking for validation errors
Corentin Wallezcab352c2019-10-28 13:27:36 +0000381 static void OnDeviceError(WGPUErrorType type, const char* message, void* userdata);
Natasha Lee0ecc48e2020-01-15 19:02:13 +0000382 static void OnDeviceLost(const char* message, void* userdata);
Corentin Wallez2dfb3f02019-02-28 09:45:48 +0000383 bool mExpectError = false;
384 bool mError = false;
385
Austin Eng0a434272020-08-04 19:46:37 +0000386 std::ostringstream& AddTextureExpectationImpl(const char* file,
387 int line,
388 detail::Expectation* expectation,
389 const wgpu::Texture& texture,
Yunchao He4eb40c12021-03-31 22:15:53 +0000390 wgpu::Origin3D origin,
391 wgpu::Extent3D extent,
Austin Eng0a434272020-08-04 19:46:37 +0000392 uint32_t level,
Austin Eng0a434272020-08-04 19:46:37 +0000393 wgpu::TextureAspect aspect,
394 uint32_t dataSize,
395 uint32_t bytesPerRow);
396
Corentin Wallez419e9842018-06-07 13:10:44 +0200397 // MapRead buffers used to get data for the expectations
398 struct ReadbackSlot {
Corentin Wallezcab352c2019-10-28 13:27:36 +0000399 wgpu::Buffer buffer;
Austin Engcf52d712019-04-05 20:51:29 +0000400 uint64_t bufferSize;
Corentin Wallez419e9842018-06-07 13:10:44 +0200401 const void* mappedData = nullptr;
402 };
403 std::vector<ReadbackSlot> mReadbackSlots;
Corentin Wallezeaae7462017-06-16 18:34:35 -0400404
Corentin Wallez419e9842018-06-07 13:10:44 +0200405 // Maps all the buffers and fill ReadbackSlot::mappedData
406 void MapSlotsSynchronously();
Corentin Wallez2a232ba2020-07-16 16:35:40 +0000407 static void SlotMapCallback(WGPUBufferMapAsyncStatus status, void* userdata);
Corentin Wallez419e9842018-06-07 13:10:44 +0200408 size_t mNumPendingMapOperations = 0;
Corentin Wallezeaae7462017-06-16 18:34:35 -0400409
Corentin Wallez419e9842018-06-07 13:10:44 +0200410 // Reserve space where the data for an expectation can be copied
411 struct ReadbackReservation {
Corentin Wallezcab352c2019-10-28 13:27:36 +0000412 wgpu::Buffer buffer;
Corentin Wallez419e9842018-06-07 13:10:44 +0200413 size_t slot;
Austin Engcf52d712019-04-05 20:51:29 +0000414 uint64_t offset;
Corentin Wallez419e9842018-06-07 13:10:44 +0200415 };
Austin Engcf52d712019-04-05 20:51:29 +0000416 ReadbackReservation ReserveReadback(uint64_t readbackSize);
Corentin Wallezeaae7462017-06-16 18:34:35 -0400417
Corentin Wallez419e9842018-06-07 13:10:44 +0200418 struct DeferredExpectation {
419 const char* file;
420 int line;
421 size_t readbackSlot;
Austin Engcf52d712019-04-05 20:51:29 +0000422 uint64_t readbackOffset;
423 uint64_t size;
Corentin Wallez419e9842018-06-07 13:10:44 +0200424 uint32_t rowBytes;
Corentin Wallezcdf2d8d2020-04-24 10:02:43 +0000425 uint32_t bytesPerRow;
Corentin Wallezcca9c692018-09-06 15:26:48 +0200426 std::unique_ptr<detail::Expectation> expectation;
Corentin Wallez419e9842018-06-07 13:10:44 +0200427 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54316
428 // Use unique_ptr because of missing move/copy constructors on std::basic_ostringstream
429 std::unique_ptr<std::ostringstream> message;
430 };
431 std::vector<DeferredExpectation> mDeferredExpectations;
Corentin Wallezeaae7462017-06-16 18:34:35 -0400432
Corentin Wallez419e9842018-06-07 13:10:44 +0200433 // Assuming the data is mapped, checks all expectations
434 void ResolveExpectations();
435
Jiawei Shao574b9512019-08-02 00:06:38 +0000436 dawn_native::Adapter mBackendAdapter;
Bryan Bernhart41b3f9c2020-11-20 20:38:37 +0000437
438 std::unique_ptr<dawn_platform::Platform> mTestPlatform;
Corentin Wallezeaae7462017-06-16 18:34:35 -0400439};
440
Austin Enge79b0612019-10-09 16:23:22 +0000441// Skip a test when the given condition is satisfied.
Zhenyao Mo5b7292c2020-04-11 03:22:33 +0000442#define DAWN_SKIP_TEST_IF(condition) \
443 do { \
444 if (condition) { \
445 dawn::InfoLog() << "Test skipped: " #condition "."; \
446 GTEST_SKIP(); \
447 return; \
448 } \
449 } while (0)
Austin Enge79b0612019-10-09 16:23:22 +0000450
Kai Ninomiya2bb80352020-10-28 21:23:45 +0000451#define EXPECT_DEPRECATION_WARNING(statement) \
452 do { \
453 if (UsesWire()) { \
454 statement; \
455 } else { \
456 size_t warningsBefore = \
457 dawn_native::GetDeprecationWarningCountForTesting(device.Get()); \
458 statement; \
459 size_t warningsAfter = \
460 dawn_native::GetDeprecationWarningCountForTesting(device.Get()); \
461 EXPECT_EQ(mLastWarningCount, warningsBefore); \
Austin Engb38a9c32020-11-14 01:09:23 +0000462 if (!HasToggleEnabled("skip_validation")) { \
Kai Ninomiya2bb80352020-10-28 21:23:45 +0000463 EXPECT_EQ(warningsAfter, warningsBefore + 1); \
464 } \
465 mLastWarningCount = warningsAfter; \
466 } \
467 } while (0)
468
Austin Engda722ad2020-05-15 20:28:05 +0000469template <typename Params = AdapterTestParam>
Austin Engca0eac32019-08-28 23:18:10 +0000470class DawnTestWithParams : public DawnTestBase, public ::testing::TestWithParam<Params> {
471 protected:
472 DawnTestWithParams();
473 ~DawnTestWithParams() override = default;
474
Austin Eng40dc5d32020-05-15 22:06:35 +0000475 void SetUp() override {
476 DawnTestBase::SetUp();
Austin Engca0eac32019-08-28 23:18:10 +0000477 }
478
479 void TearDown() override {
480 DawnTestBase::TearDown();
481 }
482};
483
484template <typename Params>
485DawnTestWithParams<Params>::DawnTestWithParams() : DawnTestBase(this->GetParam()) {
486}
487
488using DawnTest = DawnTestWithParams<>;
489
Corentin Wallez60bb88d2020-05-13 08:01:55 +0000490// Helpers to get the first element of a __VA_ARGS__ without triggering empty __VA_ARGS__ warnings.
491#define DAWN_INTERNAL_PP_GET_HEAD(firstParam, ...) firstParam
492#define DAWN_PP_GET_HEAD(...) DAWN_INTERNAL_PP_GET_HEAD(__VA_ARGS__, dummyArg)
493
Corentin Wallezeaae7462017-06-16 18:34:35 -0400494// Instantiate the test once for each backend provided after the first argument. Use it like this:
Corentin Wallezae187ef2018-07-18 15:16:37 +0200495// DAWN_INSTANTIATE_TEST(MyTestFixture, MetalBackend, OpenGLBackend)
Corentin Wallez60bb88d2020-05-13 08:01:55 +0000496#define DAWN_INSTANTIATE_TEST(testName, ...) \
497 const decltype(DAWN_PP_GET_HEAD(__VA_ARGS__)) testName##params[] = {__VA_ARGS__}; \
498 INSTANTIATE_TEST_SUITE_P( \
499 , testName, \
Austin Engda722ad2020-05-15 20:28:05 +0000500 testing::ValuesIn(::detail::GetAvailableAdapterTestParamsForBackends( \
Corentin Wallez60bb88d2020-05-13 08:01:55 +0000501 testName##params, sizeof(testName##params) / sizeof(testName##params[0]))), \
Corentin Wallezbf1e9532020-11-04 09:44:47 +0000502 testing::PrintToStringParamName()); \
503 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(testName)
Corentin Wallezeaae7462017-06-16 18:34:35 -0400504
505namespace detail {
Corentin Wallezae187ef2018-07-18 15:16:37 +0200506 // Helper functions used for DAWN_INSTANTIATE_TEST
Corentin Wallezf12c9db2020-01-10 13:28:18 +0000507 bool IsBackendAvailable(wgpu::BackendType type);
Austin Engda722ad2020-05-15 20:28:05 +0000508 std::vector<AdapterTestParam> GetAvailableAdapterTestParamsForBackends(
509 const BackendTestConfig* params,
510 size_t numParams);
Corentin Wallezeaae7462017-06-16 18:34:35 -0400511
512 // All classes used to implement the deferred expectations should inherit from this.
513 class Expectation {
Corentin Walleza4da0322018-07-18 15:18:25 +0200514 public:
515 virtual ~Expectation() = default;
Corentin Wallezeaae7462017-06-16 18:34:35 -0400516
Corentin Walleza4da0322018-07-18 15:18:25 +0200517 // Will be called with the buffer or texture data the expectation should check.
518 virtual testing::AssertionResult Check(const void* data, size_t size) = 0;
Corentin Wallezeaae7462017-06-16 18:34:35 -0400519 };
520
521 // Expectation that checks the data is equal to some expected values.
Corentin Walleza4da0322018-07-18 15:18:25 +0200522 template <typename T>
Corentin Wallezeaae7462017-06-16 18:34:35 -0400523 class ExpectEq : public Expectation {
Corentin Walleza4da0322018-07-18 15:18:25 +0200524 public:
525 ExpectEq(T singleValue);
526 ExpectEq(const T* values, const unsigned int count);
Corentin Wallezeaae7462017-06-16 18:34:35 -0400527
Corentin Walleza4da0322018-07-18 15:18:25 +0200528 testing::AssertionResult Check(const void* data, size_t size) override;
Corentin Wallezeaae7462017-06-16 18:34:35 -0400529
Corentin Walleza4da0322018-07-18 15:18:25 +0200530 private:
531 std::vector<T> mExpected;
Corentin Wallezeaae7462017-06-16 18:34:35 -0400532 };
Stephen Whitee5ae3272018-02-04 11:07:02 -0500533 extern template class ExpectEq<uint8_t>;
Xinghua Caodb8f8042020-06-08 12:18:21 +0000534 extern template class ExpectEq<int16_t>;
Corentin Wallezeaae7462017-06-16 18:34:35 -0400535 extern template class ExpectEq<uint32_t>;
Hao Lic0acb252020-08-04 06:41:56 +0000536 extern template class ExpectEq<uint64_t>;
Corentin Wallez4cd65f02017-06-27 00:11:16 -0400537 extern template class ExpectEq<RGBA8>;
Austin Eng0d661982020-01-16 00:12:10 +0000538 extern template class ExpectEq<float>;
shrekshaof8c5e4a2020-12-24 03:11:17 +0000539
540 template <typename T>
541 class ExpectBetweenColors : public Expectation {
542 public:
543 // Inclusive for now
544 ExpectBetweenColors(T value0, T value1);
545 testing::AssertionResult Check(const void* data, size_t size) override;
546
547 private:
548 std::vector<T> mLowerColorChannels;
549 std::vector<T> mHigherColorChannels;
550
551 // used for printing error
552 std::vector<T> mValues0;
553 std::vector<T> mValues1;
554 };
555 // A color is considered between color0 and color1 when all channel values are within range of
556 // each counterparts. It doesn't matter which value is higher or lower. Essentially color =
557 // lerp(color0, color1, t) where t is [0,1]. But I don't want to be too strict here.
558 extern template class ExpectBetweenColors<RGBA8>;
Corentin Walleza4da0322018-07-18 15:18:25 +0200559} // namespace detail
Austin Engca0eac32019-08-28 23:18:10 +0000560
561#endif // TESTS_DAWNTEST_H_