blob: 8e8a90bd05b27918730b94ea330bf5ebd6000845 [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
Corentin Walleza4da0322018-07-18 15:18:25 +020015#include "tests/DawnTest.h"
Corentin Wallezeaae7462017-06-16 18:34:35 -040016
Corentin Wallezfd589f32017-07-10 13:46:05 -040017#include "common/Assert.h"
Brandon Jonesd1cba102020-01-07 17:49:15 +000018#include "common/GPUInfo.h"
Corentin Wallez95586ff2019-12-05 11:13:01 +000019#include "common/Log.h"
Austin Eng51ff0132017-07-13 15:10:30 -040020#include "common/Math.h"
Jiawei Shao58809d42018-09-19 00:32:52 +000021#include "common/Platform.h"
Austin Engcbc206e2019-12-10 23:32:48 +000022#include "common/SystemUtils.h"
Corentin Wallez96496822019-10-15 11:44:38 +000023#include "dawn/dawn_proc.h"
Austin Enge2c85132019-02-11 21:50:16 +000024#include "dawn_wire/WireClient.h"
25#include "dawn_wire/WireServer.h"
Austin Eng3cd8c432021-06-01 21:25:33 +000026#include "utils/ComboRenderPipelineDescriptor.h"
Austin Engf5800962020-08-14 21:02:12 +000027#include "utils/PlatformDebugLogger.h"
Corentin Wallez134e0802017-07-17 17:13:57 -040028#include "utils/SystemUtils.h"
Corentin Wallezbdc86772018-07-26 15:07:57 +020029#include "utils/TerribleCommandBuffer.h"
Kai Ninomiyac9d0b492020-10-23 21:21:33 +000030#include "utils/TestUtils.h"
Corentin Wallez04863c42019-10-25 11:36:47 +000031#include "utils/WGPUHelpers.h"
Austin Enge58d5a32021-01-27 22:54:04 +000032#include "utils/WireHelper.h"
Corentin Wallezeaae7462017-06-16 18:34:35 -040033
Corentin Wallezbb5696b2019-02-12 15:48:15 +000034#include <algorithm>
Austin Engcbc206e2019-12-10 23:32:48 +000035#include <fstream>
Corentin Wallezfda06172019-02-21 17:36:11 +000036#include <iomanip>
Austin Engda722ad2020-05-15 20:28:05 +000037#include <regex>
Corentin Wallezfda06172019-02-21 17:36:11 +000038#include <sstream>
Corentin Wallez8c88e1d2019-02-05 12:17:20 +000039#include <unordered_map>
Brian Ho2fb628d2019-08-13 21:45:44 +000040
Austin Engf5800962020-08-14 21:02:12 +000041#if defined(DAWN_ENABLE_BACKEND_OPENGL)
Brian Ho2fb628d2019-08-13 21:45:44 +000042# include "GLFW/glfw3.h"
43# include "dawn_native/OpenGLBackend.h"
44#endif // DAWN_ENABLE_BACKEND_OPENGL
Corentin Wallez419e9842018-06-07 13:10:44 +020045
Corentin Wallezeaae7462017-06-16 18:34:35 -040046namespace {
47
Corentin Wallezf12c9db2020-01-10 13:28:18 +000048 std::string ParamName(wgpu::BackendType type) {
Corentin Walleza4da0322018-07-18 15:18:25 +020049 switch (type) {
Corentin Wallezf12c9db2020-01-10 13:28:18 +000050 case wgpu::BackendType::D3D12:
Corentin Wallezeaae7462017-06-16 18:34:35 -040051 return "D3D12";
Corentin Wallezf12c9db2020-01-10 13:28:18 +000052 case wgpu::BackendType::Metal:
Corentin Wallezeaae7462017-06-16 18:34:35 -040053 return "Metal";
Corentin Wallezf12c9db2020-01-10 13:28:18 +000054 case wgpu::BackendType::Null:
Corentin Wallez8c88e1d2019-02-05 12:17:20 +000055 return "Null";
Corentin Wallezf12c9db2020-01-10 13:28:18 +000056 case wgpu::BackendType::OpenGL:
Corentin Wallezeaae7462017-06-16 18:34:35 -040057 return "OpenGL";
Stephen Whited45ab072020-11-25 16:45:04 +000058 case wgpu::BackendType::OpenGLES:
59 return "OpenGLES";
Corentin Wallezf12c9db2020-01-10 13:28:18 +000060 case wgpu::BackendType::Vulkan:
Corentin Wallezeaae7462017-06-16 18:34:35 -040061 return "Vulkan";
62 default:
Corentin Wallez8fca4a22017-07-10 21:48:12 -040063 UNREACHABLE();
Corentin Wallezeaae7462017-06-16 18:34:35 -040064 }
65 }
66
Corentin Wallezf12c9db2020-01-10 13:28:18 +000067 const char* AdapterTypeName(wgpu::AdapterType type) {
Corentin Wallez2ec74dc2019-04-15 16:36:25 +000068 switch (type) {
Corentin Wallezf12c9db2020-01-10 13:28:18 +000069 case wgpu::AdapterType::DiscreteGPU:
Corentin Wallez2ec74dc2019-04-15 16:36:25 +000070 return "Discrete GPU";
Corentin Wallezf12c9db2020-01-10 13:28:18 +000071 case wgpu::AdapterType::IntegratedGPU:
Corentin Wallez2ec74dc2019-04-15 16:36:25 +000072 return "Integrated GPU";
Corentin Wallezf12c9db2020-01-10 13:28:18 +000073 case wgpu::AdapterType::CPU:
Corentin Wallez2ec74dc2019-04-15 16:36:25 +000074 return "CPU";
Corentin Wallezf12c9db2020-01-10 13:28:18 +000075 case wgpu::AdapterType::Unknown:
Corentin Wallez2ec74dc2019-04-15 16:36:25 +000076 return "Unknown";
77 default:
78 UNREACHABLE();
79 }
80 }
81
Corentin Wallezeaae7462017-06-16 18:34:35 -040082 struct MapReadUserdata {
Austin Engca0eac32019-08-28 23:18:10 +000083 DawnTestBase* test;
Corentin Wallezeaae7462017-06-16 18:34:35 -040084 size_t slot;
85 };
Corentin Wallez79aee9c2018-10-16 09:16:15 +000086
Corentin Wallez0b2f5522019-02-21 16:29:12 +000087 DawnTestEnvironment* gTestEnv = nullptr;
88
shrekshaof8c5e4a2020-12-24 03:11:17 +000089 template <typename T>
90 void printBuffer(testing::AssertionResult& result, const T* buffer, const size_t count) {
91 static constexpr unsigned int kBytes = sizeof(T);
92
93 for (size_t index = 0; index < count; ++index) {
94 auto byteView = reinterpret_cast<const uint8_t*>(buffer + index);
95 for (unsigned int b = 0; b < kBytes; ++b) {
96 char buf[4];
97 sprintf(buf, "%02X ", byteView[b]);
98 result << buf;
99 }
100 }
101 result << std::endl;
102 }
103
Austin Engf5800962020-08-14 21:02:12 +0000104} // anonymous namespace
Corentin Wallezeaae7462017-06-16 18:34:35 -0400105
Yunchao He0c02f542019-11-19 17:57:30 +0000106const RGBA8 RGBA8::kZero = RGBA8(0, 0, 0, 0);
107const RGBA8 RGBA8::kBlack = RGBA8(0, 0, 0, 255);
108const RGBA8 RGBA8::kRed = RGBA8(255, 0, 0, 255);
109const RGBA8 RGBA8::kGreen = RGBA8(0, 255, 0, 255);
110const RGBA8 RGBA8::kBlue = RGBA8(0, 0, 255, 255);
111const RGBA8 RGBA8::kYellow = RGBA8(255, 255, 0, 255);
112const RGBA8 RGBA8::kWhite = RGBA8(255, 255, 255, 255);
113
Austin Engda722ad2020-05-15 20:28:05 +0000114BackendTestConfig::BackendTestConfig(wgpu::BackendType backendType,
115 std::initializer_list<const char*> forceEnabledWorkarounds,
116 std::initializer_list<const char*> forceDisabledWorkarounds)
Austin Eng6c1d6462020-02-25 16:23:17 +0000117 : backendType(backendType),
118 forceEnabledWorkarounds(forceEnabledWorkarounds),
119 forceDisabledWorkarounds(forceDisabledWorkarounds) {
120}
Jiawei Shao93373ab2019-05-29 00:07:37 +0000121
Austin Engda722ad2020-05-15 20:28:05 +0000122BackendTestConfig D3D12Backend(std::initializer_list<const char*> forceEnabledWorkarounds,
123 std::initializer_list<const char*> forceDisabledWorkarounds) {
124 return BackendTestConfig(wgpu::BackendType::D3D12, forceEnabledWorkarounds,
125 forceDisabledWorkarounds);
Austin Eng6c1d6462020-02-25 16:23:17 +0000126}
127
Austin Engda722ad2020-05-15 20:28:05 +0000128BackendTestConfig MetalBackend(std::initializer_list<const char*> forceEnabledWorkarounds,
129 std::initializer_list<const char*> forceDisabledWorkarounds) {
130 return BackendTestConfig(wgpu::BackendType::Metal, forceEnabledWorkarounds,
131 forceDisabledWorkarounds);
Austin Eng6c1d6462020-02-25 16:23:17 +0000132}
133
Austin Engda722ad2020-05-15 20:28:05 +0000134BackendTestConfig NullBackend(std::initializer_list<const char*> forceEnabledWorkarounds,
135 std::initializer_list<const char*> forceDisabledWorkarounds) {
136 return BackendTestConfig(wgpu::BackendType::Null, forceEnabledWorkarounds,
137 forceDisabledWorkarounds);
Corentin Wallez11652ff2020-03-20 17:07:20 +0000138}
139
Austin Engda722ad2020-05-15 20:28:05 +0000140BackendTestConfig OpenGLBackend(std::initializer_list<const char*> forceEnabledWorkarounds,
141 std::initializer_list<const char*> forceDisabledWorkarounds) {
142 return BackendTestConfig(wgpu::BackendType::OpenGL, forceEnabledWorkarounds,
143 forceDisabledWorkarounds);
Austin Eng6c1d6462020-02-25 16:23:17 +0000144}
145
Stephen Whited45ab072020-11-25 16:45:04 +0000146BackendTestConfig OpenGLESBackend(std::initializer_list<const char*> forceEnabledWorkarounds,
147 std::initializer_list<const char*> forceDisabledWorkarounds) {
148 return BackendTestConfig(wgpu::BackendType::OpenGLES, forceEnabledWorkarounds,
149 forceDisabledWorkarounds);
150}
151
Austin Engda722ad2020-05-15 20:28:05 +0000152BackendTestConfig VulkanBackend(std::initializer_list<const char*> forceEnabledWorkarounds,
153 std::initializer_list<const char*> forceDisabledWorkarounds) {
154 return BackendTestConfig(wgpu::BackendType::Vulkan, forceEnabledWorkarounds,
155 forceDisabledWorkarounds);
Jiawei Shao15d4c2e2019-04-26 07:52:57 +0000156}
157
Austin Eng25c747c2020-05-15 16:07:12 +0000158TestAdapterProperties::TestAdapterProperties(const wgpu::AdapterProperties& properties,
159 bool selected)
160 : wgpu::AdapterProperties(properties), adapterName(properties.name), selected(selected) {
161}
162
Austin Engda722ad2020-05-15 20:28:05 +0000163AdapterTestParam::AdapterTestParam(const BackendTestConfig& config,
164 const TestAdapterProperties& adapterProperties)
165 : adapterProperties(adapterProperties),
166 forceEnabledWorkarounds(config.forceEnabledWorkarounds),
167 forceDisabledWorkarounds(config.forceDisabledWorkarounds) {
168}
169
170std::ostream& operator<<(std::ostream& os, const AdapterTestParam& param) {
Austin Enga9e39e12021-06-01 18:49:12 +0000171 os << ParamName(param.adapterProperties.backendType) << " "
172 << param.adapterProperties.adapterName;
Jiawei Shao8a3cc5c2020-05-21 00:24:16 +0000173
174 // In a Windows Remote Desktop session there are two adapters named "Microsoft Basic Render
175 // Driver" with different adapter types. We must differentiate them to avoid any tests using the
176 // same name.
177 if (param.adapterProperties.deviceID == 0x008C) {
178 std::string adapterType = AdapterTypeName(param.adapterProperties.adapterType);
Austin Enga9e39e12021-06-01 18:49:12 +0000179 os << " " << adapterType;
Jiawei Shao8a3cc5c2020-05-21 00:24:16 +0000180 }
181
Brian Hoe25a3ae2019-08-27 01:44:29 +0000182 for (const char* forceEnabledWorkaround : param.forceEnabledWorkarounds) {
Austin Enga9e39e12021-06-01 18:49:12 +0000183 os << "; e:" << forceEnabledWorkaround;
Brian Hoe25a3ae2019-08-27 01:44:29 +0000184 }
185 for (const char* forceDisabledWorkaround : param.forceDisabledWorkarounds) {
Austin Enga9e39e12021-06-01 18:49:12 +0000186 os << "; d:" << forceDisabledWorkaround;
Brian Hoe25a3ae2019-08-27 01:44:29 +0000187 }
188 return os;
189}
190
Austin Enga9e39e12021-06-01 18:49:12 +0000191DawnTestBase::PrintToStringParamName::PrintToStringParamName(const char* test) : mTest(test) {
192}
193
194std::string DawnTestBase::PrintToStringParamName::SanitizeParamName(std::string paramName,
195 size_t index) const {
196 // Sanitize the adapter name for GoogleTest
197 std::string sanitizedName = std::regex_replace(paramName, std::regex("[^a-zA-Z0-9]+"), "_");
198
199 // Strip trailing underscores, if any.
200 while (sanitizedName.back() == '_') {
201 sanitizedName.resize(sanitizedName.length() - 1);
202 }
203
204 // We don't know the the test name at this point, but the format usually looks like
205 // this.
206 std::string prefix = mTest + ".TheTestNameUsuallyGoesHere/";
207 std::string testFormat = prefix + sanitizedName;
208 if (testFormat.length() > 220) {
209 // The bots don't support test names longer than 256. Shorten the name and append a unique
210 // index if we're close. The failure log will still print the full param name.
211 std::string suffix = std::string("__") + std::to_string(index);
212 size_t targetLength = sanitizedName.length();
213 targetLength -= testFormat.length() - 220;
214 targetLength -= suffix.length();
215 sanitizedName.resize(targetLength);
216 sanitizedName = sanitizedName + suffix;
217 }
218 return sanitizedName;
219}
220
Corentin Wallez0b2f5522019-02-21 16:29:12 +0000221// Implementation of DawnTestEnvironment
222
223void InitDawnEnd2EndTestEnvironment(int argc, char** argv) {
224 gTestEnv = new DawnTestEnvironment(argc, argv);
225 testing::AddGlobalTestEnvironment(gTestEnv);
Corentin Wallez3499d3e2019-02-18 15:07:44 +0000226}
227
Austin Eng51332212020-05-15 16:04:32 +0000228// static
229void DawnTestEnvironment::SetEnvironment(DawnTestEnvironment* env) {
230 gTestEnv = env;
231}
232
Corentin Wallez0b2f5522019-02-21 16:29:12 +0000233DawnTestEnvironment::DawnTestEnvironment(int argc, char** argv) {
Austin Eng25c747c2020-05-15 16:07:12 +0000234 ParseArgs(argc, argv);
235
Brandon Jonesbdbf98a2021-02-04 19:32:12 +0000236 if (mBackendValidationLevel != dawn_native::BackendValidationLevel::Disabled) {
Bryan Bernhart6db3a242020-09-22 16:23:06 +0000237 mPlatformDebugLogger =
238 std::unique_ptr<utils::PlatformDebugLogger>(utils::CreatePlatformDebugLogger());
239 }
240
Austin Engda722ad2020-05-15 20:28:05 +0000241 // Create a temporary instance to select available and preferred adapters. This is done before
242 // test instantiation so GetAvailableAdapterTestParamsForBackends can generate test
243 // parameterizations all selected adapters. We drop the instance at the end of this function
244 // because the Vulkan validation layers use static global mutexes which behave badly when
245 // Chromium's test launcher forks the test process. The instance will be recreated on test
246 // environment setup.
Austin Eng25c747c2020-05-15 16:07:12 +0000247 std::unique_ptr<dawn_native::Instance> instance = CreateInstanceAndDiscoverAdapters();
248 ASSERT(instance);
249
Austin Engda722ad2020-05-15 20:28:05 +0000250 SelectPreferredAdapterProperties(instance.get());
Austin Engb38a9c32020-11-14 01:09:23 +0000251 PrintTestConfigurationAndAdapterInfo(instance.get());
Austin Eng25c747c2020-05-15 16:07:12 +0000252}
253
Austin Engf5800962020-08-14 21:02:12 +0000254DawnTestEnvironment::~DawnTestEnvironment() = default;
255
Austin Eng25c747c2020-05-15 16:07:12 +0000256void DawnTestEnvironment::ParseArgs(int argc, char** argv) {
Austin Eng51332212020-05-15 16:04:32 +0000257 size_t argLen = 0; // Set when parsing --arg=X arguments
Corentin Wallez0b2f5522019-02-21 16:29:12 +0000258 for (int i = 1; i < argc; ++i) {
259 if (strcmp("-w", argv[i]) == 0 || strcmp("--use-wire", argv[i]) == 0) {
260 mUseWire = true;
261 continue;
262 }
263
Jiawei Shao3fd20362021-05-19 08:31:13 +0000264 if (strcmp("--run-suppressed-tests", argv[i]) == 0) {
265 mRunSuppressedTests = true;
266 continue;
267 }
268
Brandon Jonesbdbf98a2021-02-04 19:32:12 +0000269 constexpr const char kEnableBackendValidationSwitch[] = "--enable-backend-validation";
270 argLen = sizeof(kEnableBackendValidationSwitch) - 1;
271 if (strncmp(argv[i], kEnableBackendValidationSwitch, argLen) == 0) {
272 const char* level = argv[i] + argLen;
273 if (level[0] != '\0') {
274 if (strcmp(level, "=full") == 0) {
275 mBackendValidationLevel = dawn_native::BackendValidationLevel::Full;
276 } else if (strcmp(level, "=partial") == 0) {
277 mBackendValidationLevel = dawn_native::BackendValidationLevel::Partial;
278 } else if (strcmp(level, "=disabled") == 0) {
279 mBackendValidationLevel = dawn_native::BackendValidationLevel::Disabled;
280 } else {
281 dawn::ErrorLog() << "Invalid backend validation level" << level;
282 UNREACHABLE();
283 }
284 } else {
Bryan Bernharte688e522021-04-26 18:26:36 +0000285 mBackendValidationLevel = dawn_native::BackendValidationLevel::Partial;
Brandon Jonesbdbf98a2021-02-04 19:32:12 +0000286 }
Bryan Bernhart5ff49782021-03-22 17:18:46 +0000287 continue;
Li Hao0195dbf2019-05-15 06:06:26 +0000288 }
289
Rafael Cintron4729b152019-06-21 02:09:05 +0000290 if (strcmp("-c", argv[i]) == 0 || strcmp("--begin-capture-on-startup", argv[i]) == 0) {
291 mBeginCaptureOnStartup = true;
292 continue;
293 }
294
Ryan Harrisonacdc35d2021-04-14 14:55:07 +0000295 if (mToggleParser.ParseEnabledToggles(argv[i])) {
Austin Engb38a9c32020-11-14 01:09:23 +0000296 continue;
297 }
298
Ryan Harrisonacdc35d2021-04-14 14:55:07 +0000299 if (mToggleParser.ParseDisabledToggles(argv[i])) {
Austin Eng4d156092019-11-21 00:48:39 +0000300 continue;
301 }
302
Austin Eng92a011a2019-10-17 19:00:32 +0000303 constexpr const char kVendorIdFilterArg[] = "--adapter-vendor-id=";
Austin Eng51332212020-05-15 16:04:32 +0000304 argLen = sizeof(kVendorIdFilterArg) - 1;
305 if (strncmp(argv[i], kVendorIdFilterArg, argLen) == 0) {
306 const char* vendorIdFilter = argv[i] + argLen;
Austin Eng92a011a2019-10-17 19:00:32 +0000307 if (vendorIdFilter[0] != '\0') {
308 mVendorIdFilter = strtoul(vendorIdFilter, nullptr, 16);
Li, Hao35716c22019-07-08 03:25:54 +0000309 // Set filter flag if vendor id is non-zero.
310 mHasVendorIdFilter = mVendorIdFilter != 0;
311 }
312 continue;
313 }
314
Austin Engda722ad2020-05-15 20:28:05 +0000315 constexpr const char kExclusiveDeviceTypePreferenceArg[] =
316 "--exclusive-device-type-preference=";
317 argLen = sizeof(kExclusiveDeviceTypePreferenceArg) - 1;
318 if (strncmp(argv[i], kExclusiveDeviceTypePreferenceArg, argLen) == 0) {
319 const char* preference = argv[i] + argLen;
320 if (preference[0] != '\0') {
321 std::istringstream ss(preference);
322 std::string type;
323 while (std::getline(ss, type, ',')) {
324 if (strcmp(type.c_str(), "discrete") == 0) {
325 mDevicePreferences.push_back(dawn_native::DeviceType::DiscreteGPU);
326 } else if (strcmp(type.c_str(), "integrated") == 0) {
327 mDevicePreferences.push_back(dawn_native::DeviceType::IntegratedGPU);
328 } else if (strcmp(type.c_str(), "cpu") == 0) {
329 mDevicePreferences.push_back(dawn_native::DeviceType::CPU);
330 } else {
331 dawn::ErrorLog() << "Invalid device type preference: " << type;
332 UNREACHABLE();
333 }
334 }
335 }
Bryan Bernhart5ff49782021-03-22 17:18:46 +0000336 continue;
Austin Engda722ad2020-05-15 20:28:05 +0000337 }
338
Austin Engcbc206e2019-12-10 23:32:48 +0000339 constexpr const char kWireTraceDirArg[] = "--wire-trace-dir=";
Austin Eng51332212020-05-15 16:04:32 +0000340 argLen = sizeof(kWireTraceDirArg) - 1;
341 if (strncmp(argv[i], kWireTraceDirArg, argLen) == 0) {
Austin Enge58d5a32021-01-27 22:54:04 +0000342 mWireTraceDir = argv[i] + argLen;
Austin Engcbc206e2019-12-10 23:32:48 +0000343 continue;
344 }
345
Stephen Whiteeb71aaf2021-02-17 17:07:08 +0000346 constexpr const char kBackendArg[] = "--backend=";
347 argLen = sizeof(kBackendArg) - 1;
348 if (strncmp(argv[i], kBackendArg, argLen) == 0) {
349 const char* param = argv[i] + argLen;
350 if (strcmp("d3d12", param) == 0) {
351 mBackendTypeFilter = wgpu::BackendType::D3D12;
352 } else if (strcmp("metal", param) == 0) {
353 mBackendTypeFilter = wgpu::BackendType::Metal;
354 } else if (strcmp("null", param) == 0) {
355 mBackendTypeFilter = wgpu::BackendType::Null;
356 } else if (strcmp("opengl", param) == 0) {
357 mBackendTypeFilter = wgpu::BackendType::OpenGL;
358 } else if (strcmp("opengles", param) == 0) {
359 mBackendTypeFilter = wgpu::BackendType::OpenGLES;
360 } else if (strcmp("vulkan", param) == 0) {
361 mBackendTypeFilter = wgpu::BackendType::Vulkan;
362 } else {
363 dawn::ErrorLog()
364 << "Invalid backend \"" << param
365 << "\". Valid backends are: d3d12, metal, null, opengl, opengles, vulkan.";
366 UNREACHABLE();
367 }
368 mHasBackendTypeFilter = true;
369 continue;
370 }
Corentin Wallez0b2f5522019-02-21 16:29:12 +0000371 if (strcmp("-h", argv[i]) == 0 || strcmp("--help", argv[i]) == 0) {
Corentin Wallezdc3317d2019-12-06 18:21:39 +0000372 dawn::InfoLog()
373 << "\n\nUsage: " << argv[0]
Brandon Jonesbdbf98a2021-02-04 19:32:12 +0000374 << " [GTEST_FLAGS...] [-w] [-c]\n"
Austin Engb38a9c32020-11-14 01:09:23 +0000375 " [--enable-toggles=toggles] [--disable-toggles=toggles]\n"
Stephen Whiteeb71aaf2021-02-17 17:07:08 +0000376 " [--backend=x]\n"
Brandon Jonesbdbf98a2021-02-04 19:32:12 +0000377 " [--adapter-vendor-id=x] "
378 "[--enable-backend-validation[=full,partial,disabled]]\n"
379 " [--exclusive-device-type-preference=integrated,cpu,discrete]\n\n"
Corentin Wallezdc3317d2019-12-06 18:21:39 +0000380 " -w, --use-wire: Run the tests through the wire (defaults to no wire)\n"
Corentin Wallezdc3317d2019-12-06 18:21:39 +0000381 " -c, --begin-capture-on-startup: Begin debug capture on startup "
382 "(defaults to no capture)\n"
Bryan Bernharte688e522021-04-26 18:26:36 +0000383 " --enable-backend-validation: Enables backend validation. Defaults to \n"
384 " 'partial' to enable only minimum backend validation. Set to 'full' to\n"
385 " enable all available backend validation with less performance overhead.\n"
Brandon Jonesbdbf98a2021-02-04 19:32:12 +0000386 " Set to 'disabled' to run with no validation (same as no flag).\n"
Austin Engb38a9c32020-11-14 01:09:23 +0000387 " --enable-toggles: Comma-delimited list of Dawn toggles to enable.\n"
Corentin Wallezdeb40572021-10-29 13:17:27 +0000388 " ex.) skip_validation,disable_robustness,turn_off_vsync\n"
Austin Engb38a9c32020-11-14 01:09:23 +0000389 " --disable-toggles: Comma-delimited list of Dawn toggles to disable\n"
Corentin Wallezdc3317d2019-12-06 18:21:39 +0000390 " --adapter-vendor-id: Select adapter by vendor id to run end2end tests"
Austin Engda722ad2020-05-15 20:28:05 +0000391 "on multi-GPU systems \n"
Stephen Whiteeb71aaf2021-02-17 17:07:08 +0000392 " --backend: Select adapter by backend type. Valid backends are: d3d12, metal, "
393 "null, opengl, opengles, vulkan\n"
Austin Engda722ad2020-05-15 20:28:05 +0000394 " --exclusive-device-type-preference: Comma-delimited list of preferred device "
395 "types. For each backend, tests will run only on adapters that match the first "
Jiawei Shao3fd20362021-05-19 08:31:13 +0000396 "available device type\n"
397 " --run-suppressed-tests: Run all the tests that will be skipped by the macro "
398 "DAWN_SUPPRESS_TEST_IF()\n";
Corentin Wallez0b2f5522019-02-21 16:29:12 +0000399 continue;
400 }
Austin Eng7124cc42021-02-25 20:38:45 +0000401
402 // Skip over args that look like they're for Googletest.
403 constexpr const char kGtestArgPrefix[] = "--gtest_";
404 if (strncmp(kGtestArgPrefix, argv[i], sizeof(kGtestArgPrefix) - 1) == 0) {
405 continue;
406 }
407
408 dawn::WarningLog() << " Unused argument: " << argv[i];
Corentin Wallez0b2f5522019-02-21 16:29:12 +0000409 }
410}
411
Stephen Whited45ab072020-11-25 16:45:04 +0000412std::unique_ptr<dawn_native::Instance> DawnTestEnvironment::CreateInstanceAndDiscoverAdapters() {
Austin Eng51332212020-05-15 16:04:32 +0000413 auto instance = std::make_unique<dawn_native::Instance>();
Austin Eng51332212020-05-15 16:04:32 +0000414 instance->EnableBeginCaptureOnStartup(mBeginCaptureOnStartup);
Brandon Jonesbdbf98a2021-02-04 19:32:12 +0000415 instance->SetBackendValidationLevel(mBackendValidationLevel);
Austin Eng51332212020-05-15 16:04:32 +0000416 instance->DiscoverDefaultAdapters();
417
Stephen White21ce5d22021-05-17 18:04:48 +0000418#ifdef DAWN_ENABLE_BACKEND_DESKTOP_GL
Austin Eng51332212020-05-15 16:04:32 +0000419 if (!glfwInit()) {
420 return instance;
421 }
422 glfwDefaultWindowHints();
423 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
424 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
425 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
426 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
Stephen Whiteeb7108c2021-01-27 17:22:44 +0000427 glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
Austin Eng51332212020-05-15 16:04:32 +0000428
Stephen Whited45ab072020-11-25 16:45:04 +0000429 mOpenGLWindow = glfwCreateWindow(400, 400, "Dawn OpenGL test window", nullptr, nullptr);
Austin Eng51332212020-05-15 16:04:32 +0000430
Stephen Whited45ab072020-11-25 16:45:04 +0000431 glfwMakeContextCurrent(mOpenGLWindow);
Austin Eng51332212020-05-15 16:04:32 +0000432 dawn_native::opengl::AdapterDiscoveryOptions adapterOptions;
433 adapterOptions.getProc = reinterpret_cast<void* (*)(const char*)>(glfwGetProcAddress);
434 instance->DiscoverAdapters(&adapterOptions);
Stephen White21ce5d22021-05-17 18:04:48 +0000435#endif // DAWN_ENABLE_BACKEND_DESKTOP_GL
436
437#ifdef DAWN_ENABLE_BACKEND_OPENGLES
Stephen Whited45ab072020-11-25 16:45:04 +0000438
Austin Eng09c308c2021-11-16 23:37:15 +0000439 ScopedEnvironmentVar angleDefaultPlatform;
440 if (GetEnvironmentVar("ANGLE_DEFAULT_PLATFORM").first.empty()) {
441 angleDefaultPlatform.Set("ANGLE_DEFAULT_PLATFORM", "swiftshader");
Stephen Whitee7e42eb2021-02-08 21:30:44 +0000442 }
Austin Eng09c308c2021-11-16 23:37:15 +0000443
Stephen White21ce5d22021-05-17 18:04:48 +0000444 if (!glfwInit()) {
445 return instance;
446 }
Stephen Whited45ab072020-11-25 16:45:04 +0000447 glfwDefaultWindowHints();
448 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
449 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
450 glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
451 glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
Stephen Whiteeb7108c2021-01-27 17:22:44 +0000452 glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
Stephen Whited45ab072020-11-25 16:45:04 +0000453
454 mOpenGLESWindow = glfwCreateWindow(400, 400, "Dawn OpenGLES test window", nullptr, nullptr);
455
456 glfwMakeContextCurrent(mOpenGLESWindow);
457 dawn_native::opengl::AdapterDiscoveryOptionsES adapterOptionsES;
Stephen White21ce5d22021-05-17 18:04:48 +0000458 adapterOptionsES.getProc = reinterpret_cast<void* (*)(const char*)>(glfwGetProcAddress);
Stephen Whited45ab072020-11-25 16:45:04 +0000459 instance->DiscoverAdapters(&adapterOptionsES);
Stephen Whiteeb7108c2021-01-27 17:22:44 +0000460 glfwWindowHint(GLFW_VISIBLE, GLFW_TRUE);
Stephen White21ce5d22021-05-17 18:04:48 +0000461#endif // DAWN_ENABLE_BACKEND_OPENGLES
Austin Eng51332212020-05-15 16:04:32 +0000462
463 return instance;
Austin Engca0eac32019-08-28 23:18:10 +0000464}
465
Stephen Whited45ab072020-11-25 16:45:04 +0000466GLFWwindow* DawnTestEnvironment::GetOpenGLWindow() const {
467 return mOpenGLWindow;
468}
469
470GLFWwindow* DawnTestEnvironment::GetOpenGLESWindow() const {
471 return mOpenGLESWindow;
472}
473
Austin Engda722ad2020-05-15 20:28:05 +0000474void DawnTestEnvironment::SelectPreferredAdapterProperties(const dawn_native::Instance* instance) {
475 // Get the first available preferred device type.
476 dawn_native::DeviceType preferredDeviceType = static_cast<dawn_native::DeviceType>(-1);
477 bool hasDevicePreference = false;
478 for (dawn_native::DeviceType devicePreference : mDevicePreferences) {
479 for (const dawn_native::Adapter& adapter : instance->GetAdapters()) {
480 wgpu::AdapterProperties properties;
481 adapter.GetProperties(&properties);
482
483 if (adapter.GetDeviceType() == devicePreference) {
484 preferredDeviceType = devicePreference;
485 hasDevicePreference = true;
486 break;
487 }
488 }
489 if (hasDevicePreference) {
490 break;
491 }
492 }
493
Jiawei Shaoe87a8c42020-11-05 08:38:46 +0000494 std::set<std::pair<wgpu::BackendType, std::string>> adapterNameSet;
Austin Eng25c747c2020-05-15 16:07:12 +0000495 for (const dawn_native::Adapter& adapter : instance->GetAdapters()) {
496 wgpu::AdapterProperties properties;
497 adapter.GetProperties(&properties);
498
Stephen Whiteeb71aaf2021-02-17 17:07:08 +0000499 // All adapters are selected by default.
500 bool selected = true;
501 // The adapter is deselected if:
502 if (mHasBackendTypeFilter) {
503 // It doesn't match the backend type, if present.
504 selected &= properties.backendType == mBackendTypeFilter;
505 }
Austin Engda722ad2020-05-15 20:28:05 +0000506 if (mHasVendorIdFilter) {
Stephen Whiteeb71aaf2021-02-17 17:07:08 +0000507 // It doesn't match the vendor id, if present.
508 selected &= mVendorIdFilter == properties.vendorID;
Austin Engda722ad2020-05-15 20:28:05 +0000509
510 if (!mDevicePreferences.empty()) {
511 dawn::WarningLog() << "Vendor ID filter provided. Ignoring device type preference.";
512 }
Stephen Whiteeb71aaf2021-02-17 17:07:08 +0000513 }
514 if (hasDevicePreference) {
Austin Engda722ad2020-05-15 20:28:05 +0000515 // There is a device preference and:
Stephen Whiteeb71aaf2021-02-17 17:07:08 +0000516 selected &=
517 // The device type doesn't match the first available preferred type for that
518 // backend, if present.
Austin Engda722ad2020-05-15 20:28:05 +0000519 (adapter.GetDeviceType() == preferredDeviceType) ||
520 // Always select Unknown OpenGL adapters if we don't want a CPU adapter.
521 // OpenGL will usually be unknown because we can't query the device type.
522 // If we ever have Swiftshader GL (unlikely), we could set the DeviceType properly.
523 (preferredDeviceType != dawn_native::DeviceType::CPU &&
524 adapter.GetDeviceType() == dawn_native::DeviceType::Unknown &&
Stephen White040f1402021-02-03 17:36:29 +0000525 (properties.backendType == wgpu::BackendType::OpenGL ||
526 properties.backendType == wgpu::BackendType::OpenGLES)) ||
Austin Engda722ad2020-05-15 20:28:05 +0000527 // Always select the Null backend. There are few tests on this backend, and they run
528 // quickly. This is temporary as to not lose coverage. We can group it with
529 // Swiftshader as a CPU adapter when we have Swiftshader tests.
530 (properties.backendType == wgpu::BackendType::Null);
Austin Engda722ad2020-05-15 20:28:05 +0000531 }
532
Jiawei Shaoe87a8c42020-11-05 08:38:46 +0000533 // In Windows Remote Desktop sessions we may be able to discover multiple adapters that
534 // have the same name and backend type. We will just choose one adapter from them in our
535 // tests.
536 const auto adapterTypeAndName =
537 std::make_pair(properties.backendType, std::string(properties.name));
538 if (adapterNameSet.find(adapterTypeAndName) == adapterNameSet.end()) {
539 adapterNameSet.insert(adapterTypeAndName);
540 mAdapterProperties.emplace_back(properties, selected);
541 }
Austin Eng25c747c2020-05-15 16:07:12 +0000542 }
543}
544
Austin Engda722ad2020-05-15 20:28:05 +0000545std::vector<AdapterTestParam> DawnTestEnvironment::GetAvailableAdapterTestParamsForBackends(
546 const BackendTestConfig* params,
547 size_t numParams) {
548 std::vector<AdapterTestParam> testParams;
Austin Eng25c747c2020-05-15 16:07:12 +0000549 for (size_t i = 0; i < numParams; ++i) {
550 for (const auto& adapterProperties : mAdapterProperties) {
Austin Engda722ad2020-05-15 20:28:05 +0000551 if (params[i].backendType == adapterProperties.backendType &&
552 adapterProperties.selected) {
553 testParams.push_back(AdapterTestParam(params[i], adapterProperties));
Austin Eng25c747c2020-05-15 16:07:12 +0000554 }
555 }
556 }
Austin Engda722ad2020-05-15 20:28:05 +0000557 return testParams;
Austin Eng25c747c2020-05-15 16:07:12 +0000558}
559
Austin Engb38a9c32020-11-14 01:09:23 +0000560void DawnTestEnvironment::PrintTestConfigurationAndAdapterInfo(
561 dawn_native::Instance* instance) const {
Austin Eng51332212020-05-15 16:04:32 +0000562 dawn::LogMessage log = dawn::InfoLog();
563 log << "Testing configuration\n"
564 "---------------------\n"
565 "UseWire: "
566 << (mUseWire ? "true" : "false")
567 << "\n"
Jiawei Shao3fd20362021-05-19 08:31:13 +0000568 "Run suppressed tests: "
569 << (mRunSuppressedTests ? "true" : "false")
570 << "\n"
Brandon Jonesbdbf98a2021-02-04 19:32:12 +0000571 "BackendValidation: ";
572
573 switch (mBackendValidationLevel) {
574 case dawn_native::BackendValidationLevel::Full:
575 log << "full";
576 break;
577 case dawn_native::BackendValidationLevel::Partial:
578 log << "partial";
579 break;
580 case dawn_native::BackendValidationLevel::Disabled:
581 log << "disabled";
582 break;
583 default:
584 UNREACHABLE();
585 }
Austin Engb38a9c32020-11-14 01:09:23 +0000586
587 if (GetEnabledToggles().size() > 0) {
588 log << "\n"
589 "Enabled Toggles\n";
590 for (const std::string& toggle : GetEnabledToggles()) {
591 const dawn_native::ToggleInfo* info = instance->GetToggleInfo(toggle.c_str());
592 ASSERT(info != nullptr);
593 log << " - " << info->name << ": " << info->description << "\n";
594 }
595 }
596
597 if (GetDisabledToggles().size() > 0) {
598 log << "\n"
599 "Disabled Toggles\n";
600 for (const std::string& toggle : GetDisabledToggles()) {
601 const dawn_native::ToggleInfo* info = instance->GetToggleInfo(toggle.c_str());
602 ASSERT(info != nullptr);
603 log << " - " << info->name << ": " << info->description << "\n";
604 }
605 }
606
607 log << "\n"
Austin Eng51332212020-05-15 16:04:32 +0000608 "BeginCaptureOnStartup: "
609 << (mBeginCaptureOnStartup ? "true" : "false")
610 << "\n"
611 "\n"
612 << "System adapters: \n";
Corentin Wallez0b2f5522019-02-21 16:29:12 +0000613
Austin Eng25c747c2020-05-15 16:07:12 +0000614 for (const TestAdapterProperties& properties : mAdapterProperties) {
Corentin Wallezfda06172019-02-21 17:36:11 +0000615 std::ostringstream vendorId;
616 std::ostringstream deviceId;
617 vendorId << std::setfill('0') << std::uppercase << std::internal << std::hex << std::setw(4)
Corentin Wallezf12c9db2020-01-10 13:28:18 +0000618 << properties.vendorID;
Corentin Wallezfda06172019-02-21 17:36:11 +0000619 deviceId << std::setfill('0') << std::uppercase << std::internal << std::hex << std::setw(4)
Corentin Wallezf12c9db2020-01-10 13:28:18 +0000620 << properties.deviceID;
Corentin Wallezfda06172019-02-21 17:36:11 +0000621
Corentin Wallez95586ff2019-12-05 11:13:01 +0000622 // Preparing for outputting hex numbers
Austin Eng51332212020-05-15 16:04:32 +0000623 log << std::showbase << std::hex << std::setfill('0') << std::setw(4)
Corentin Wallez95586ff2019-12-05 11:13:01 +0000624
Corentin Wallez73b70222020-10-14 13:33:15 +0000625 << " - \"" << properties.adapterName << "\" - \"" << properties.driverDescription
626 << "\"\n"
Austin Eng51332212020-05-15 16:04:32 +0000627 << " type: " << AdapterTypeName(properties.adapterType)
628 << ", backend: " << ParamName(properties.backendType) << "\n"
629 << " vendorId: 0x" << vendorId.str() << ", deviceId: 0x" << deviceId.str()
Austin Eng25c747c2020-05-15 16:07:12 +0000630 << (properties.selected ? " [Selected]" : "") << "\n";
Corentin Wallezfda06172019-02-21 17:36:11 +0000631 }
Corentin Wallez0b2f5522019-02-21 16:29:12 +0000632}
633
Austin Eng51332212020-05-15 16:04:32 +0000634void DawnTestEnvironment::SetUp() {
635 mInstance = CreateInstanceAndDiscoverAdapters();
636 ASSERT(mInstance);
Austin Eng51332212020-05-15 16:04:32 +0000637}
638
Jiajie Hu9e5b9ed2019-11-20 09:45:41 +0000639void DawnTestEnvironment::TearDown() {
640 // When Vulkan validation layers are enabled, it's unsafe to call Vulkan APIs in the destructor
641 // of a static/global variable, so the instance must be manually released beforehand.
642 mInstance.reset();
643}
644
Corentin Wallez0ee98592019-05-01 12:57:27 +0000645bool DawnTestEnvironment::UsesWire() const {
Corentin Wallez0b2f5522019-02-21 16:29:12 +0000646 return mUseWire;
647}
648
Jiawei Shao3fd20362021-05-19 08:31:13 +0000649bool DawnTestEnvironment::RunSuppressedTests() const {
650 return mRunSuppressedTests;
651}
652
Brandon Jonesbdbf98a2021-02-04 19:32:12 +0000653dawn_native::BackendValidationLevel DawnTestEnvironment::GetBackendValidationLevel() const {
654 return mBackendValidationLevel;
Li, Hao6fa398e2019-06-25 00:49:56 +0000655}
656
Corentin Wallez0b2f5522019-02-21 16:29:12 +0000657dawn_native::Instance* DawnTestEnvironment::GetInstance() const {
658 return mInstance.get();
659}
660
Li, Hao35716c22019-07-08 03:25:54 +0000661bool DawnTestEnvironment::HasVendorIdFilter() const {
662 return mHasVendorIdFilter;
663}
664
665uint32_t DawnTestEnvironment::GetVendorIdFilter() const {
666 return mVendorIdFilter;
667}
668
Stephen Whiteeb71aaf2021-02-17 17:07:08 +0000669bool DawnTestEnvironment::HasBackendTypeFilter() const {
670 return mHasBackendTypeFilter;
671}
672
673wgpu::BackendType DawnTestEnvironment::GetBackendTypeFilter() const {
674 return mBackendTypeFilter;
675}
676
Austin Engcbc206e2019-12-10 23:32:48 +0000677const char* DawnTestEnvironment::GetWireTraceDir() const {
678 if (mWireTraceDir.length() == 0) {
679 return nullptr;
680 }
681 return mWireTraceDir.c_str();
682}
683
Austin Engb38a9c32020-11-14 01:09:23 +0000684const std::vector<std::string>& DawnTestEnvironment::GetEnabledToggles() const {
Ryan Harrisonacdc35d2021-04-14 14:55:07 +0000685 return mToggleParser.GetEnabledToggles();
Austin Engb38a9c32020-11-14 01:09:23 +0000686}
687
688const std::vector<std::string>& DawnTestEnvironment::GetDisabledToggles() const {
Ryan Harrisonacdc35d2021-04-14 14:55:07 +0000689 return mToggleParser.GetDisabledToggles();
Austin Engb38a9c32020-11-14 01:09:23 +0000690}
691
Corentin Wallez0b2f5522019-02-21 16:29:12 +0000692// Implementation of DawnTest
693
Austin Enge58d5a32021-01-27 22:54:04 +0000694DawnTestBase::DawnTestBase(const AdapterTestParam& param)
695 : mParam(param),
696 mWireHelper(utils::CreateWireHelper(gTestEnv->UsesWire(), gTestEnv->GetWireTraceDir())) {
Austin Engca0eac32019-08-28 23:18:10 +0000697}
Corentin Wallezcca9c692018-09-06 15:26:48 +0200698
Austin Engca0eac32019-08-28 23:18:10 +0000699DawnTestBase::~DawnTestBase() {
Corentin Wallezeaae7462017-06-16 18:34:35 -0400700 // We need to destroy child objects before the Device
Corentin Wallezd5d77af2017-11-23 11:51:16 -0800701 mReadbackSlots.clear();
Corentin Wallezcab352c2019-10-28 13:27:36 +0000702 queue = wgpu::Queue();
703 device = wgpu::Device();
Corentin Wallezeaae7462017-06-16 18:34:35 -0400704
Brandon Jones0a295c02021-02-24 22:09:30 +0000705 // D3D12's GPU-based validation will accumulate objects over time if the backend device is not
706 // destroyed and recreated, so we reset it here.
707 if (IsD3D12() && IsBackendValidationEnabled()) {
708 mBackendAdapter.ResetInternalDeviceForTesting();
709 }
Austin Enge58d5a32021-01-27 22:54:04 +0000710 mWireHelper.reset();
Corentin Wallezeaae7462017-06-16 18:34:35 -0400711}
712
Austin Engca0eac32019-08-28 23:18:10 +0000713bool DawnTestBase::IsD3D12() const {
Austin Engda722ad2020-05-15 20:28:05 +0000714 return mParam.adapterProperties.backendType == wgpu::BackendType::D3D12;
Austin Eng77a29982017-07-12 20:36:36 -0400715}
716
Austin Engca0eac32019-08-28 23:18:10 +0000717bool DawnTestBase::IsMetal() const {
Austin Engda722ad2020-05-15 20:28:05 +0000718 return mParam.adapterProperties.backendType == wgpu::BackendType::Metal;
Corentin Walleze1f16a22017-07-18 10:31:50 -0400719}
720
Corentin Wallez11652ff2020-03-20 17:07:20 +0000721bool DawnTestBase::IsNull() const {
Austin Engda722ad2020-05-15 20:28:05 +0000722 return mParam.adapterProperties.backendType == wgpu::BackendType::Null;
Corentin Wallez11652ff2020-03-20 17:07:20 +0000723}
724
Austin Engca0eac32019-08-28 23:18:10 +0000725bool DawnTestBase::IsOpenGL() const {
Austin Engda722ad2020-05-15 20:28:05 +0000726 return mParam.adapterProperties.backendType == wgpu::BackendType::OpenGL;
Corentin Walleze1f16a22017-07-18 10:31:50 -0400727}
728
Stephen Whited45ab072020-11-25 16:45:04 +0000729bool DawnTestBase::IsOpenGLES() const {
730 return mParam.adapterProperties.backendType == wgpu::BackendType::OpenGLES;
731}
732
Austin Engca0eac32019-08-28 23:18:10 +0000733bool DawnTestBase::IsVulkan() const {
Austin Engda722ad2020-05-15 20:28:05 +0000734 return mParam.adapterProperties.backendType == wgpu::BackendType::Vulkan;
Corentin Walleze1f16a22017-07-18 10:31:50 -0400735}
736
Austin Engca0eac32019-08-28 23:18:10 +0000737bool DawnTestBase::IsAMD() const {
Austin Engda722ad2020-05-15 20:28:05 +0000738 return gpu_info::IsAMD(mParam.adapterProperties.vendorID);
Jiawei Shao58809d42018-09-19 00:32:52 +0000739}
740
Austin Engca0eac32019-08-28 23:18:10 +0000741bool DawnTestBase::IsARM() const {
Austin Engda722ad2020-05-15 20:28:05 +0000742 return gpu_info::IsARM(mParam.adapterProperties.vendorID);
Jiawei Shao58809d42018-09-19 00:32:52 +0000743}
744
Austin Engca0eac32019-08-28 23:18:10 +0000745bool DawnTestBase::IsImgTec() const {
Austin Engda722ad2020-05-15 20:28:05 +0000746 return gpu_info::IsImgTec(mParam.adapterProperties.vendorID);
Jiawei Shao58809d42018-09-19 00:32:52 +0000747}
748
Austin Engca0eac32019-08-28 23:18:10 +0000749bool DawnTestBase::IsIntel() const {
Austin Engda722ad2020-05-15 20:28:05 +0000750 return gpu_info::IsIntel(mParam.adapterProperties.vendorID);
Jiawei Shao58809d42018-09-19 00:32:52 +0000751}
752
Austin Engca0eac32019-08-28 23:18:10 +0000753bool DawnTestBase::IsNvidia() const {
Austin Engda722ad2020-05-15 20:28:05 +0000754 return gpu_info::IsNvidia(mParam.adapterProperties.vendorID);
Jiawei Shao58809d42018-09-19 00:32:52 +0000755}
756
Austin Engca0eac32019-08-28 23:18:10 +0000757bool DawnTestBase::IsQualcomm() const {
Austin Engda722ad2020-05-15 20:28:05 +0000758 return gpu_info::IsQualcomm(mParam.adapterProperties.vendorID);
Jiawei Shao58809d42018-09-19 00:32:52 +0000759}
760
Corentin Wallezd56b69f2020-04-09 08:16:30 +0000761bool DawnTestBase::IsSwiftshader() const {
Austin Engda722ad2020-05-15 20:28:05 +0000762 return gpu_info::IsSwiftshader(mParam.adapterProperties.vendorID,
763 mParam.adapterProperties.deviceID);
Corentin Wallezd56b69f2020-04-09 08:16:30 +0000764}
765
Stephen Whitef09a6702021-01-18 17:47:07 +0000766bool DawnTestBase::IsANGLE() const {
767 return !mParam.adapterProperties.adapterName.find("ANGLE");
768}
769
Bryan Bernhart8c255ac2020-07-10 22:58:48 +0000770bool DawnTestBase::IsWARP() const {
771 return gpu_info::IsWARP(mParam.adapterProperties.vendorID, mParam.adapterProperties.deviceID);
772}
773
Austin Engca0eac32019-08-28 23:18:10 +0000774bool DawnTestBase::IsWindows() const {
Jiawei Shao58809d42018-09-19 00:32:52 +0000775#ifdef DAWN_PLATFORM_WINDOWS
776 return true;
777#else
778 return false;
779#endif
780}
781
Austin Engca0eac32019-08-28 23:18:10 +0000782bool DawnTestBase::IsLinux() const {
Jiawei Shao58809d42018-09-19 00:32:52 +0000783#ifdef DAWN_PLATFORM_LINUX
784 return true;
785#else
786 return false;
787#endif
788}
789
Austin Enge50f8c62021-07-21 18:34:19 +0000790bool DawnTestBase::IsMacOS(int32_t majorVersion, int32_t minorVersion) const {
James Price565863e2021-08-05 20:35:19 +0000791#ifdef DAWN_PLATFORM_MACOS
Austin Enge50f8c62021-07-21 18:34:19 +0000792 if (majorVersion == -1 && minorVersion == -1) {
793 return true;
794 }
795 int32_t majorVersionOut, minorVersionOut = 0;
796 GetMacOSVersion(&majorVersionOut, &minorVersionOut);
797 return (majorVersion != -1 && majorVersion == majorVersionOut) &&
798 (minorVersion != -1 && minorVersion == minorVersionOut);
Jiawei Shao58809d42018-09-19 00:32:52 +0000799#else
800 return false;
801#endif
802}
803
Austin Engca0eac32019-08-28 23:18:10 +0000804bool DawnTestBase::UsesWire() const {
Corentin Wallez0ee98592019-05-01 12:57:27 +0000805 return gTestEnv->UsesWire();
806}
807
Austin Engca0eac32019-08-28 23:18:10 +0000808bool DawnTestBase::IsBackendValidationEnabled() const {
Brandon Jonesbdbf98a2021-02-04 19:32:12 +0000809 return gTestEnv->GetBackendValidationLevel() != dawn_native::BackendValidationLevel::Disabled;
Li, Hao6fa398e2019-06-25 00:49:56 +0000810}
811
Jiawei Shao3fd20362021-05-19 08:31:13 +0000812bool DawnTestBase::RunSuppressedTests() const {
813 return gTestEnv->RunSuppressedTests();
814}
815
Ben Claytoncd417bc2021-06-16 20:18:08 +0000816bool DawnTestBase::IsDXC() const {
817 return HasToggleEnabled("use_dxc");
818}
819
Austin Eng0e9e5ee2020-06-19 17:35:33 +0000820bool DawnTestBase::IsAsan() const {
821#if defined(ADDRESS_SANITIZER)
822 return true;
823#else
824 return false;
825#endif
826}
827
Enrico Galli2b6b0f42020-11-05 18:52:49 +0000828bool DawnTestBase::HasToggleEnabled(const char* toggle) const {
Austin Engf731a812020-12-04 02:07:20 +0000829 auto toggles = dawn_native::GetTogglesUsed(backendDevice);
Austin Engb38a9c32020-11-14 01:09:23 +0000830 return std::find_if(toggles.begin(), toggles.end(), [toggle](const char* name) {
831 return strcmp(toggle, name) == 0;
832 }) != toggles.end();
Enrico Galli2b6b0f42020-11-05 18:52:49 +0000833}
834
Austin Engca0eac32019-08-28 23:18:10 +0000835bool DawnTestBase::HasVendorIdFilter() const {
Li, Hao35716c22019-07-08 03:25:54 +0000836 return gTestEnv->HasVendorIdFilter();
837}
838
Austin Engca0eac32019-08-28 23:18:10 +0000839uint32_t DawnTestBase::GetVendorIdFilter() const {
Li, Hao35716c22019-07-08 03:25:54 +0000840 return gTestEnv->GetVendorIdFilter();
841}
842
Stephen Whiteeb71aaf2021-02-17 17:07:08 +0000843bool DawnTestBase::HasBackendTypeFilter() const {
844 return gTestEnv->HasBackendTypeFilter();
845}
846
847wgpu::BackendType DawnTestBase::GetBackendTypeFilter() const {
848 return gTestEnv->GetBackendTypeFilter();
849}
850
Corentin Wallez11652ff2020-03-20 17:07:20 +0000851wgpu::Instance DawnTestBase::GetInstance() const {
852 return gTestEnv->GetInstance()->Get();
853}
854
855dawn_native::Adapter DawnTestBase::GetAdapter() const {
856 return mBackendAdapter;
857}
858
François Beaufort3f689a42021-10-04 11:30:02 +0000859std::vector<const char*> DawnTestBase::GetRequiredFeatures() {
Jiawei Shao574b9512019-08-02 00:06:38 +0000860 return {};
861}
862
Austin Eng26ae0ea2021-10-19 16:06:21 +0000863wgpu::RequiredLimits DawnTestBase::GetRequiredLimits(const wgpu::SupportedLimits&) {
864 return {};
865}
866
Corentin Wallezf12c9db2020-01-10 13:28:18 +0000867const wgpu::AdapterProperties& DawnTestBase::GetAdapterProperties() const {
Austin Engda722ad2020-05-15 20:28:05 +0000868 return mParam.adapterProperties;
Corentin Wallezf12c9db2020-01-10 13:28:18 +0000869}
870
Austin Eng91851e22021-10-13 18:57:18 +0000871wgpu::SupportedLimits DawnTestBase::GetSupportedLimits() {
872 WGPUSupportedLimits supportedLimits;
873 supportedLimits.nextInChain = nullptr;
874 dawn_native::GetProcs().deviceGetLimits(backendDevice, &supportedLimits);
875 return *reinterpret_cast<wgpu::SupportedLimits*>(&supportedLimits);
876}
877
François Beaufort3f689a42021-10-04 11:30:02 +0000878bool DawnTestBase::SupportsFeatures(const std::vector<const char*>& features) {
Jiawei Shao574b9512019-08-02 00:06:38 +0000879 ASSERT(mBackendAdapter);
François Beaufort3f689a42021-10-04 11:30:02 +0000880 std::set<std::string> supportedFeaturesSet;
881 for (const char* supportedFeatureName : mBackendAdapter.GetSupportedFeatures()) {
882 supportedFeaturesSet.insert(supportedFeatureName);
Jiawei Shao574b9512019-08-02 00:06:38 +0000883 }
884
François Beaufort3f689a42021-10-04 11:30:02 +0000885 for (const char* featureName : features) {
886 if (supportedFeaturesSet.find(featureName) == supportedFeaturesSet.end()) {
Jiawei Shao574b9512019-08-02 00:06:38 +0000887 return false;
888 }
889 }
890
891 return true;
892}
893
Austin Engca0eac32019-08-28 23:18:10 +0000894void DawnTestBase::SetUp() {
Corentin Wallezbb5696b2019-02-12 15:48:15 +0000895 {
Austin Engda722ad2020-05-15 20:28:05 +0000896 // Find the adapter that exactly matches our adapter properties.
897 const auto& adapters = gTestEnv->GetInstance()->GetAdapters();
898 const auto& it = std::find_if(
899 adapters.begin(), adapters.end(), [&](const dawn_native::Adapter& adapter) {
900 wgpu::AdapterProperties properties;
901 adapter.GetProperties(&properties);
Corentin Wallezaf5d1862019-02-27 10:09:46 +0000902
Austin Engda722ad2020-05-15 20:28:05 +0000903 return (mParam.adapterProperties.selected &&
904 properties.deviceID == mParam.adapterProperties.deviceID &&
905 properties.vendorID == mParam.adapterProperties.vendorID &&
906 properties.adapterType == mParam.adapterProperties.adapterType &&
907 properties.backendType == mParam.adapterProperties.backendType &&
908 strcmp(properties.name, mParam.adapterProperties.adapterName.c_str()) == 0);
909 });
910 ASSERT(it != adapters.end());
911 mBackendAdapter = *it;
Corentin Wallezbb5696b2019-02-12 15:48:15 +0000912 }
913
Bryan Bernhart41b3f9c2020-11-20 20:38:37 +0000914 // Setup the per-test platform. Tests can provide one by overloading CreateTestPlatform.
915 mTestPlatform = CreateTestPlatform();
916 gTestEnv->GetInstance()->SetPlatform(mTestPlatform.get());
917
Austin Engda722ad2020-05-15 20:28:05 +0000918 // Create the device from the adapter
Austin Engca0eac32019-08-28 23:18:10 +0000919 for (const char* forceEnabledWorkaround : mParam.forceEnabledWorkarounds) {
Natasha Lee97f08fa2019-05-11 00:21:50 +0000920 ASSERT(gTestEnv->GetInstance()->GetToggleInfo(forceEnabledWorkaround) != nullptr);
Jiawei Shao15d4c2e2019-04-26 07:52:57 +0000921 }
Austin Engca0eac32019-08-28 23:18:10 +0000922 for (const char* forceDisabledWorkaround : mParam.forceDisabledWorkarounds) {
Natasha Lee28232ce2019-06-11 18:11:05 +0000923 ASSERT(gTestEnv->GetInstance()->GetToggleInfo(forceDisabledWorkaround) != nullptr);
924 }
Austin Eng3482a802021-11-23 18:03:16 +0000925 dawn_native::DawnDeviceDescriptor deviceDescriptor = {};
Austin Engca0eac32019-08-28 23:18:10 +0000926 deviceDescriptor.forceEnabledToggles = mParam.forceEnabledWorkarounds;
927 deviceDescriptor.forceDisabledToggles = mParam.forceDisabledWorkarounds;
François Beaufort3f689a42021-10-04 11:30:02 +0000928 deviceDescriptor.requiredFeatures = GetRequiredFeatures();
Austin Eng4d156092019-11-21 00:48:39 +0000929
Austin Eng26ae0ea2021-10-19 16:06:21 +0000930 wgpu::SupportedLimits supportedLimits;
931 mBackendAdapter.GetLimits(reinterpret_cast<WGPUSupportedLimits*>(&supportedLimits));
932 wgpu::RequiredLimits requiredLimits = GetRequiredLimits(supportedLimits);
933 deviceDescriptor.requiredLimits = reinterpret_cast<WGPURequiredLimits*>(&requiredLimits);
934
Corentin Wallez07987ed2021-02-01 16:22:08 +0000935 // Disabled disallowing unsafe APIs so we can test them.
936 deviceDescriptor.forceDisabledToggles.push_back("disallow_unsafe_apis");
937
Austin Engb38a9c32020-11-14 01:09:23 +0000938 for (const std::string& toggle : gTestEnv->GetEnabledToggles()) {
939 const dawn_native::ToggleInfo* info =
940 gTestEnv->GetInstance()->GetToggleInfo(toggle.c_str());
941 ASSERT(info != nullptr);
942 deviceDescriptor.forceEnabledToggles.push_back(info->name);
943 }
944
945 for (const std::string& toggle : gTestEnv->GetDisabledToggles()) {
946 const dawn_native::ToggleInfo* info =
947 gTestEnv->GetInstance()->GetToggleInfo(toggle.c_str());
948 ASSERT(info != nullptr);
949 deviceDescriptor.forceDisabledToggles.push_back(info->name);
Austin Eng4d156092019-11-21 00:48:39 +0000950 }
951
Austin Enge58d5a32021-01-27 22:54:04 +0000952 std::tie(device, backendDevice) =
953 mWireHelper->RegisterDevice(mBackendAdapter.CreateDevice(&deviceDescriptor));
Jiawei Shao574b9512019-08-02 00:06:38 +0000954 ASSERT_NE(nullptr, backendDevice);
Jiawei Shao15d4c2e2019-04-26 07:52:57 +0000955
Austin Enge58d5a32021-01-27 22:54:04 +0000956 std::string traceName =
957 std::string(::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name()) +
958 "_" + ::testing::UnitTest::GetInstance()->current_test_info()->name();
959 mWireHelper->BeginWireTrace(traceName.c_str());
Corentin Wallezeaae7462017-06-16 18:34:35 -0400960
Corentin Wallez6d315da2021-02-04 15:33:42 +0000961 queue = device.GetQueue();
Corentin Wallezeaae7462017-06-16 18:34:35 -0400962
Austin Eng45ea7e62019-08-27 21:43:56 +0000963 device.SetUncapturedErrorCallback(OnDeviceError, this);
Natasha Lee0ecc48e2020-01-15 19:02:13 +0000964 device.SetDeviceLostCallback(OnDeviceLost, this);
Stephen White21ce5d22021-05-17 18:04:48 +0000965#if defined(DAWN_ENABLE_BACKEND_DESKTOP_GL)
Stephen Whited45ab072020-11-25 16:45:04 +0000966 if (IsOpenGL()) {
967 glfwMakeContextCurrent(gTestEnv->GetOpenGLWindow());
Stephen White21ce5d22021-05-17 18:04:48 +0000968 }
969#endif // defined(DAWN_ENABLE_BACKEND_DESKTOP_GL)
970#if defined(DAWN_ENABLE_BACKEND_OPENGLES)
971 if (IsOpenGLES()) {
Stephen Whited45ab072020-11-25 16:45:04 +0000972 glfwMakeContextCurrent(gTestEnv->GetOpenGLESWindow());
973 }
Stephen White21ce5d22021-05-17 18:04:48 +0000974#endif // defined(DAWN_ENABLE_BACKEND_OPENGLES)
Ben Clayton93a75932021-07-15 09:09:38 +0000975
976 device.SetLoggingCallback(
977 [](WGPULoggingType type, char const* message, void*) {
978 switch (type) {
979 case WGPULoggingType_Verbose:
980 dawn::DebugLog() << message;
981 break;
982 case WGPULoggingType_Warning:
983 dawn::WarningLog() << message;
984 break;
985 case WGPULoggingType_Error:
986 dawn::ErrorLog() << message;
987 break;
988 default:
989 dawn::InfoLog() << message;
990 break;
991 }
992 },
993 nullptr);
Corentin Wallezeaae7462017-06-16 18:34:35 -0400994}
995
Austin Engca0eac32019-08-28 23:18:10 +0000996void DawnTestBase::TearDown() {
Corentin Wallez419e9842018-06-07 13:10:44 +0200997 FlushWire();
998
Corentin Wallezeaae7462017-06-16 18:34:35 -0400999 MapSlotsSynchronously();
1000 ResolveExpectations();
1001
Corentin Wallezd5d77af2017-11-23 11:51:16 -08001002 for (size_t i = 0; i < mReadbackSlots.size(); ++i) {
1003 mReadbackSlots[i].buffer.Unmap();
Corentin Wallez7218ed12017-07-25 11:29:28 -04001004 }
Kai Ninomiya2bb80352020-10-28 21:23:45 +00001005
1006 if (!UsesWire()) {
1007 EXPECT_EQ(mLastWarningCount,
1008 dawn_native::GetDeprecationWarningCountForTesting(device.Get()));
1009 }
Corentin Wallezeaae7462017-06-16 18:34:35 -04001010}
1011
Austin Engca0eac32019-08-28 23:18:10 +00001012void DawnTestBase::StartExpectDeviceError() {
Corentin Wallez2dfb3f02019-02-28 09:45:48 +00001013 mExpectError = true;
1014 mError = false;
1015}
Austin Engca0eac32019-08-28 23:18:10 +00001016bool DawnTestBase::EndExpectDeviceError() {
Corentin Wallez2dfb3f02019-02-28 09:45:48 +00001017 mExpectError = false;
1018 return mError;
1019}
1020
1021// static
Corentin Wallezcab352c2019-10-28 13:27:36 +00001022void DawnTestBase::OnDeviceError(WGPUErrorType type, const char* message, void* userdata) {
1023 ASSERT(type != WGPUErrorType_NoError);
Austin Engca0eac32019-08-28 23:18:10 +00001024 DawnTestBase* self = static_cast<DawnTestBase*>(userdata);
Corentin Wallez2dfb3f02019-02-28 09:45:48 +00001025
1026 ASSERT_TRUE(self->mExpectError) << "Got unexpected device error: " << message;
1027 ASSERT_FALSE(self->mError) << "Got two errors in expect block";
1028 self->mError = true;
1029}
1030
Kai Ninomiya51791e02021-09-28 11:52:17 +00001031void DawnTestBase::OnDeviceLost(WGPUDeviceLostReason reason, const char* message, void* userdata) {
Enrico Galli101a5822020-08-08 01:05:59 +00001032 // Using ADD_FAILURE + ASSERT instead of FAIL to prevent the current test from continuing with a
1033 // corrupt state.
1034 ADD_FAILURE() << "Device Lost during test: " << message;
1035 ASSERT(false);
Natasha Lee0ecc48e2020-01-15 19:02:13 +00001036}
1037
Austin Engca0eac32019-08-28 23:18:10 +00001038std::ostringstream& DawnTestBase::AddBufferExpectation(const char* file,
1039 int line,
Corentin Wallezcab352c2019-10-28 13:27:36 +00001040 const wgpu::Buffer& buffer,
Austin Engca0eac32019-08-28 23:18:10 +00001041 uint64_t offset,
1042 uint64_t size,
1043 detail::Expectation* expectation) {
Corentin Wallezeaae7462017-06-16 18:34:35 -04001044 auto readback = ReserveReadback(size);
1045
1046 // We need to enqueue the copy immediately because by the time we resolve the expectation,
1047 // the buffer might have been modified.
Corentin Wallezcab352c2019-10-28 13:27:36 +00001048 wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
Corentin Walleze1f0d4e2019-02-15 12:54:08 +00001049 encoder.CopyBufferToBuffer(buffer, offset, readback.buffer, readback.offset, size);
Corentin Wallezeaae7462017-06-16 18:34:35 -04001050
Corentin Wallezcab352c2019-10-28 13:27:36 +00001051 wgpu::CommandBuffer commands = encoder.Finish();
Corentin Wallezeaae7462017-06-16 18:34:35 -04001052 queue.Submit(1, &commands);
1053
1054 DeferredExpectation deferred;
1055 deferred.file = file;
1056 deferred.line = line;
1057 deferred.readbackSlot = readback.slot;
1058 deferred.readbackOffset = readback.offset;
1059 deferred.size = size;
Austin Eng51ff0132017-07-13 15:10:30 -04001060 deferred.rowBytes = size;
Corentin Wallezcdf2d8d2020-04-24 10:02:43 +00001061 deferred.bytesPerRow = size;
Corentin Wallezcca9c692018-09-06 15:26:48 +02001062 deferred.expectation.reset(expectation);
Corentin Wallezeaae7462017-06-16 18:34:35 -04001063
Corentin Wallezd5d77af2017-11-23 11:51:16 -08001064 mDeferredExpectations.push_back(std::move(deferred));
1065 mDeferredExpectations.back().message = std::make_unique<std::ostringstream>();
1066 return *(mDeferredExpectations.back().message.get());
Corentin Wallezeaae7462017-06-16 18:34:35 -04001067}
1068
Austin Eng0a434272020-08-04 19:46:37 +00001069std::ostringstream& DawnTestBase::AddTextureExpectationImpl(const char* file,
1070 int line,
1071 detail::Expectation* expectation,
1072 const wgpu::Texture& texture,
Yunchao He4eb40c12021-03-31 22:15:53 +00001073 wgpu::Origin3D origin,
1074 wgpu::Extent3D extent,
Austin Eng0a434272020-08-04 19:46:37 +00001075 uint32_t level,
Austin Eng0a434272020-08-04 19:46:37 +00001076 wgpu::TextureAspect aspect,
1077 uint32_t dataSize,
1078 uint32_t bytesPerRow) {
1079 if (bytesPerRow == 0) {
Yunchao He4eb40c12021-03-31 22:15:53 +00001080 bytesPerRow = Align(extent.width * dataSize, kTextureBytesPerRowAlignment);
Austin Eng0a434272020-08-04 19:46:37 +00001081 } else {
Yunchao He4eb40c12021-03-31 22:15:53 +00001082 ASSERT(bytesPerRow >= extent.width * dataSize);
Austin Eng0a434272020-08-04 19:46:37 +00001083 ASSERT(bytesPerRow == Align(bytesPerRow, kTextureBytesPerRowAlignment));
1084 }
Corentin Wallez4cd65f02017-06-27 00:11:16 -04001085
Yunchao He4eb40c12021-03-31 22:15:53 +00001086 uint32_t rowsPerImage = extent.height;
1087 uint32_t size = utils::RequiredBytesInCopy(bytesPerRow, rowsPerImage, extent.width,
Yunchao He3e8f3f92021-04-01 22:40:43 +00001088 extent.height, extent.depthOrArrayLayers, dataSize);
Austin Eng0a434272020-08-04 19:46:37 +00001089
Austin Eng0a434272020-08-04 19:46:37 +00001090 auto readback = ReserveReadback(Align(size, 4));
Corentin Wallez4cd65f02017-06-27 00:11:16 -04001091
1092 // We need to enqueue the copy immediately because by the time we resolve the expectation,
1093 // the texture might have been modified.
Yunchao Heff55b2f2021-04-07 16:57:11 +00001094 wgpu::ImageCopyTexture imageCopyTexture =
1095 utils::CreateImageCopyTexture(texture, level, origin, aspect);
Corentin Wallez80915842021-03-04 18:13:45 +00001096 wgpu::ImageCopyBuffer imageCopyBuffer =
1097 utils::CreateImageCopyBuffer(readback.buffer, readback.offset, bytesPerRow, rowsPerImage);
Corentin Wallez4cd65f02017-06-27 00:11:16 -04001098
Corentin Wallezcab352c2019-10-28 13:27:36 +00001099 wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
Yunchao He4eb40c12021-03-31 22:15:53 +00001100 encoder.CopyTextureToBuffer(&imageCopyTexture, &imageCopyBuffer, &extent);
Corentin Walleze1f0d4e2019-02-15 12:54:08 +00001101
Corentin Wallezcab352c2019-10-28 13:27:36 +00001102 wgpu::CommandBuffer commands = encoder.Finish();
Corentin Wallez4cd65f02017-06-27 00:11:16 -04001103 queue.Submit(1, &commands);
1104
1105 DeferredExpectation deferred;
1106 deferred.file = file;
1107 deferred.line = line;
1108 deferred.readbackSlot = readback.slot;
1109 deferred.readbackOffset = readback.offset;
1110 deferred.size = size;
Yunchao He4eb40c12021-03-31 22:15:53 +00001111 deferred.rowBytes = extent.width * dataSize;
Corentin Wallezcdf2d8d2020-04-24 10:02:43 +00001112 deferred.bytesPerRow = bytesPerRow;
Corentin Wallezcca9c692018-09-06 15:26:48 +02001113 deferred.expectation.reset(expectation);
Corentin Wallez4cd65f02017-06-27 00:11:16 -04001114
Corentin Wallezd5d77af2017-11-23 11:51:16 -08001115 mDeferredExpectations.push_back(std::move(deferred));
1116 mDeferredExpectations.back().message = std::make_unique<std::ostringstream>();
1117 return *(mDeferredExpectations.back().message.get());
Corentin Wallez4cd65f02017-06-27 00:11:16 -04001118}
1119
Austin Eng75c50672021-06-24 02:01:46 +00001120std::ostringstream& DawnTestBase::ExpectSampledFloatDataImpl(wgpu::TextureView textureView,
1121 const char* wgslTextureType,
1122 uint32_t width,
1123 uint32_t height,
1124 uint32_t componentCount,
1125 uint32_t sampleCount,
1126 detail::Expectation* expectation) {
Austin Eng3cd8c432021-06-01 21:25:33 +00001127 std::ostringstream shaderSource;
1128 shaderSource << "let width : u32 = " << width << "u;\n";
Austin Eng75c50672021-06-24 02:01:46 +00001129 shaderSource << "[[group(0), binding(0)]] var tex : " << wgslTextureType << ";\n";
Austin Eng3cd8c432021-06-01 21:25:33 +00001130 shaderSource << R"(
1131 [[block]] struct Result {
1132 values : array<f32>;
1133 };
Ben Clayton15eba9a2021-06-08 15:36:44 +00001134 [[group(0), binding(1)]] var<storage, read_write> result : Result;
Austin Eng75c50672021-06-24 02:01:46 +00001135 )";
1136 shaderSource << "let componentCount : u32 = " << componentCount << "u;\n";
1137 shaderSource << "let sampleCount : u32 = " << sampleCount << "u;\n";
Austin Eng3cd8c432021-06-01 21:25:33 +00001138
Austin Eng75c50672021-06-24 02:01:46 +00001139 shaderSource << "fn doTextureLoad(t: " << wgslTextureType
1140 << ", coord: vec2<i32>, sample: u32, component: u32) -> f32";
1141 if (sampleCount > 1) {
1142 shaderSource << R"({
1143 return textureLoad(tex, coord, i32(sample))[component];
1144 })";
1145 } else {
1146 if (strcmp(wgslTextureType, "texture_depth_2d") == 0) {
1147 ASSERT(componentCount == 1);
1148 shaderSource << R"({
1149 return textureLoad(tex, coord, 0);
1150 })";
1151 } else {
1152 shaderSource << R"({
1153 return textureLoad(tex, coord, 0)[component];
1154 })";
1155 }
1156 }
1157 shaderSource << R"(
Sarah2a57db72021-06-23 19:19:06 +00001158 [[stage(compute), workgroup_size(1)]] fn main(
Austin Eng3cd8c432021-06-01 21:25:33 +00001159 [[builtin(global_invocation_id)]] GlobalInvocationId : vec3<u32>
1160 ) {
Austin Eng75c50672021-06-24 02:01:46 +00001161 let baseOutIndex = GlobalInvocationId.y * width + GlobalInvocationId.x;
1162 for (var s = 0u; s < sampleCount; s = s + 1u) {
1163 for (var c = 0u; c < componentCount; c = c + 1u) {
1164 result.values[
1165 baseOutIndex * sampleCount * componentCount +
1166 s * componentCount +
1167 c
1168 ] = doTextureLoad(tex, vec2<i32>(GlobalInvocationId.xy), s, c);
1169 }
1170 }
Austin Eng3cd8c432021-06-01 21:25:33 +00001171 }
1172 )";
1173
1174 wgpu::ShaderModule csModule = utils::CreateShaderModule(device, shaderSource.str().c_str());
1175
1176 wgpu::ComputePipelineDescriptor pipelineDescriptor;
Brandon Jones0d50a2c2021-06-09 18:07:32 +00001177 pipelineDescriptor.compute.module = csModule;
1178 pipelineDescriptor.compute.entryPoint = "main";
Austin Eng3cd8c432021-06-01 21:25:33 +00001179
1180 wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&pipelineDescriptor);
1181
1182 // Create and initialize the slot buffer so that it won't unexpectedly affect the count of
1183 // resources lazily cleared.
Austin Eng75c50672021-06-24 02:01:46 +00001184 const std::vector<float> initialBufferData(width * height * componentCount * sampleCount, 0.f);
Austin Eng3cd8c432021-06-01 21:25:33 +00001185 wgpu::Buffer readbackBuffer = utils::CreateBufferFromData(
Austin Eng75c50672021-06-24 02:01:46 +00001186 device, initialBufferData.data(), sizeof(float) * initialBufferData.size(),
Austin Eng3cd8c432021-06-01 21:25:33 +00001187 wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::Storage);
1188
Austin Eng75c50672021-06-24 02:01:46 +00001189 wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
1190 {{0, textureView}, {1, readbackBuffer}});
Austin Eng3cd8c432021-06-01 21:25:33 +00001191
1192 wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
1193 wgpu::ComputePassEncoder pass = commandEncoder.BeginComputePass();
1194 pass.SetPipeline(pipeline);
1195 pass.SetBindGroup(0, bindGroup);
1196 pass.Dispatch(width, height);
1197 pass.EndPass();
1198 wgpu::CommandBuffer commands = commandEncoder.Finish();
1199 queue.Submit(1, &commands);
1200
Austin Eng75c50672021-06-24 02:01:46 +00001201 return EXPECT_BUFFER(readbackBuffer, 0, initialBufferData.size() * sizeof(float), expectation);
1202}
1203
1204std::ostringstream& DawnTestBase::ExpectSampledFloatData(wgpu::Texture texture,
1205 uint32_t width,
1206 uint32_t height,
1207 uint32_t componentCount,
1208 uint32_t arrayLayer,
1209 uint32_t mipLevel,
1210 detail::Expectation* expectation) {
1211 wgpu::TextureViewDescriptor viewDesc = {};
1212 viewDesc.dimension = wgpu::TextureViewDimension::e2D;
1213 viewDesc.baseMipLevel = mipLevel;
1214 viewDesc.mipLevelCount = 1;
1215 viewDesc.baseArrayLayer = arrayLayer;
1216 viewDesc.arrayLayerCount = 1;
1217
1218 return ExpectSampledFloatDataImpl(texture.CreateView(&viewDesc), "texture_2d<f32>", width,
1219 height, componentCount, 1, expectation);
1220}
1221
1222std::ostringstream& DawnTestBase::ExpectMultisampledFloatData(wgpu::Texture texture,
1223 uint32_t width,
1224 uint32_t height,
1225 uint32_t componentCount,
1226 uint32_t sampleCount,
1227 uint32_t arrayLayer,
1228 uint32_t mipLevel,
1229 detail::Expectation* expectation) {
1230 wgpu::TextureViewDescriptor viewDesc = {};
1231 viewDesc.dimension = wgpu::TextureViewDimension::e2D;
1232 viewDesc.baseMipLevel = mipLevel;
1233 viewDesc.mipLevelCount = 1;
1234 viewDesc.baseArrayLayer = arrayLayer;
1235 viewDesc.arrayLayerCount = 1;
1236
1237 return ExpectSampledFloatDataImpl(texture.CreateView(&viewDesc), "texture_multisampled_2d<f32>",
1238 width, height, componentCount, sampleCount, expectation);
1239}
1240
1241std::ostringstream& DawnTestBase::ExpectSampledDepthData(wgpu::Texture texture,
1242 uint32_t width,
1243 uint32_t height,
1244 uint32_t arrayLayer,
1245 uint32_t mipLevel,
1246 detail::Expectation* expectation) {
1247 wgpu::TextureViewDescriptor viewDesc = {};
1248 viewDesc.aspect = wgpu::TextureAspect::DepthOnly;
1249 viewDesc.dimension = wgpu::TextureViewDimension::e2D;
1250 viewDesc.baseMipLevel = mipLevel;
1251 viewDesc.mipLevelCount = 1;
1252 viewDesc.baseArrayLayer = arrayLayer;
1253 viewDesc.arrayLayerCount = 1;
1254
1255 return ExpectSampledFloatDataImpl(texture.CreateView(&viewDesc), "texture_depth_2d", width,
1256 height, 1, 1, expectation);
Austin Eng735d5042021-06-08 00:24:43 +00001257}
1258
1259std::ostringstream& DawnTestBase::ExpectAttachmentDepthStencilTestData(
1260 wgpu::Texture texture,
1261 wgpu::TextureFormat format,
1262 uint32_t width,
1263 uint32_t height,
1264 uint32_t arrayLayer,
1265 uint32_t mipLevel,
1266 std::vector<float> expectedDepth,
1267 uint8_t* expectedStencil) {
1268 wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
1269
1270 // Make the color attachment that we'll use to read back.
1271 wgpu::TextureDescriptor colorTexDesc = {};
1272 colorTexDesc.size = {width, height, 1};
1273 colorTexDesc.format = wgpu::TextureFormat::R32Uint;
1274 colorTexDesc.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc;
1275 wgpu::Texture colorTexture = device.CreateTexture(&colorTexDesc);
1276
1277 wgpu::Texture depthDataTexture = nullptr;
1278 if (expectedDepth.size() > 0) {
1279 // Make a sampleable texture to store the depth data. We'll sample this in the
1280 // shader to output depth.
1281 wgpu::TextureDescriptor depthDataDesc = {};
1282 depthDataDesc.size = {width, height, 1};
1283 depthDataDesc.format = wgpu::TextureFormat::R32Float;
Brandon Jones27e17a62021-08-10 04:07:37 +00001284 depthDataDesc.usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopyDst;
Austin Eng735d5042021-06-08 00:24:43 +00001285 depthDataTexture = device.CreateTexture(&depthDataDesc);
1286
1287 // Upload the depth data.
1288 wgpu::ImageCopyTexture imageCopyTexture =
1289 utils::CreateImageCopyTexture(depthDataTexture, 0, {0, 0, 0});
1290 wgpu::TextureDataLayout textureDataLayout =
1291 utils::CreateTextureDataLayout(0, sizeof(float) * width);
1292 wgpu::Extent3D copyExtent = {width, height, 1};
1293
1294 queue.WriteTexture(&imageCopyTexture, expectedDepth.data(),
1295 sizeof(float) * expectedDepth.size(), &textureDataLayout, &copyExtent);
1296 }
1297
1298 // Pipeline for a full screen quad.
1299 utils::ComboRenderPipelineDescriptor pipelineDescriptor;
1300
1301 pipelineDescriptor.vertex.module = utils::CreateShaderModule(device, R"(
1302 [[stage(vertex)]]
1303 fn main([[builtin(vertex_index)]] VertexIndex : u32) -> [[builtin(position)]] vec4<f32> {
Corentin Wallezb86e45f2021-06-17 21:36:11 +00001304 var pos = array<vec2<f32>, 3>(
Austin Eng735d5042021-06-08 00:24:43 +00001305 vec2<f32>(-1.0, -1.0),
1306 vec2<f32>( 3.0, -1.0),
1307 vec2<f32>(-1.0, 3.0));
1308 return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
1309 })");
1310
1311 if (depthDataTexture) {
1312 // Sample the input texture and write out depth. |result| will only be set to 1 if we
1313 // pass the depth test.
1314 pipelineDescriptor.cFragment.module = utils::CreateShaderModule(device, R"(
1315 [[group(0), binding(0)]] var texture0 : texture_2d<f32>;
1316
1317 struct FragmentOut {
1318 [[location(0)]] result : u32;
1319 [[builtin(frag_depth)]] fragDepth : f32;
1320 };
1321
1322 [[stage(fragment)]]
1323 fn main([[builtin(position)]] FragCoord : vec4<f32>) -> FragmentOut {
1324 var output : FragmentOut;
1325 output.result = 1u;
1326 output.fragDepth = textureLoad(texture0, vec2<i32>(FragCoord.xy), 0)[0];
1327 return output;
1328 })");
1329 } else {
1330 pipelineDescriptor.cFragment.module = utils::CreateShaderModule(device, R"(
1331 [[stage(fragment)]]
1332 fn main() -> [[location(0)]] u32 {
1333 return 1u;
1334 })");
1335 }
1336
1337 wgpu::DepthStencilState* depthStencil = pipelineDescriptor.EnableDepthStencil(format);
1338 if (depthDataTexture) {
1339 // Pass the depth test only if the depth is equal.
1340 depthStencil->depthCompare = wgpu::CompareFunction::Equal;
1341
1342 // TODO(jiawei.shao@intel.com): The Intel Mesa Vulkan driver can't set gl_FragDepth unless
1343 // depthWriteEnabled == true. This either needs to be fixed in the driver or restricted by
1344 // the WebGPU API.
1345 depthStencil->depthWriteEnabled = true;
1346 }
1347
1348 if (expectedStencil != nullptr) {
1349 // Pass the stencil test only if the stencil is equal.
1350 depthStencil->stencilFront.compare = wgpu::CompareFunction::Equal;
1351 }
1352
1353 pipelineDescriptor.cTargets[0].format = colorTexDesc.format;
1354
1355 wgpu::TextureViewDescriptor viewDesc = {};
1356 viewDesc.baseMipLevel = mipLevel;
1357 viewDesc.mipLevelCount = 1;
1358 viewDesc.baseArrayLayer = arrayLayer;
1359 viewDesc.arrayLayerCount = 1;
1360
1361 utils::ComboRenderPassDescriptor passDescriptor({colorTexture.CreateView()},
1362 texture.CreateView(&viewDesc));
1363 passDescriptor.cDepthStencilAttachmentInfo.depthLoadOp = wgpu::LoadOp::Load;
1364 passDescriptor.cDepthStencilAttachmentInfo.stencilLoadOp = wgpu::LoadOp::Load;
1365
1366 wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDescriptor);
1367
1368 wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&passDescriptor);
1369 if (expectedStencil != nullptr) {
1370 pass.SetStencilReference(*expectedStencil);
1371 }
1372 pass.SetPipeline(pipeline);
1373 if (depthDataTexture) {
1374 // Bind the depth data texture.
1375 pass.SetBindGroup(0, utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
1376 {{0, depthDataTexture.CreateView()}}));
1377 }
1378 pass.Draw(3);
1379 pass.EndPass();
1380
1381 wgpu::CommandBuffer commands = commandEncoder.Finish();
1382 queue.Submit(1, &commands);
1383
1384 std::vector<uint32_t> colorData(width * height, 1u);
1385 return EXPECT_TEXTURE_EQ(colorData.data(), colorTexture, {0, 0}, {width, height});
Austin Eng3cd8c432021-06-01 21:25:33 +00001386}
1387
Austin Engca0eac32019-08-28 23:18:10 +00001388void DawnTestBase::WaitABit() {
Corentin Wallez134e0802017-07-17 17:13:57 -04001389 device.Tick();
Corentin Wallez419e9842018-06-07 13:10:44 +02001390 FlushWire();
1391
Corentin Wallez134e0802017-07-17 17:13:57 -04001392 utils::USleep(100);
1393}
1394
Austin Engca0eac32019-08-28 23:18:10 +00001395void DawnTestBase::FlushWire() {
Corentin Wallez0ee98592019-05-01 12:57:27 +00001396 if (gTestEnv->UsesWire()) {
Austin Enge58d5a32021-01-27 22:54:04 +00001397 bool C2SFlushed = mWireHelper->FlushClient();
1398 bool S2CFlushed = mWireHelper->FlushServer();
Corentin Wallez6be3b972019-02-11 23:34:52 +00001399 ASSERT(C2SFlushed);
1400 ASSERT(S2CFlushed);
Corentin Wallez419e9842018-06-07 13:10:44 +02001401 }
1402}
1403
Natasha Lee51af1b42020-10-12 22:32:33 +00001404void DawnTestBase::WaitForAllOperations() {
Corentin Wallez4165c1c2021-02-25 21:47:15 +00001405 bool done = false;
1406 device.GetQueue().OnSubmittedWorkDone(
1407 0u, [](WGPUQueueWorkDoneStatus, void* userdata) { *static_cast<bool*>(userdata) = true; },
1408 &done);
1409 while (!done) {
Natasha Lee51af1b42020-10-12 22:32:33 +00001410 WaitABit();
1411 }
1412}
1413
Austin Engca0eac32019-08-28 23:18:10 +00001414DawnTestBase::ReadbackReservation DawnTestBase::ReserveReadback(uint64_t readbackSize) {
Corentin Wallezeaae7462017-06-16 18:34:35 -04001415 ReadbackSlot slot;
1416 slot.bufferSize = readbackSize;
Jiawei Shaoef744732020-08-23 06:08:05 +00001417
1418 // Create and initialize the slot buffer so that it won't unexpectedly affect the count of
1419 // resource lazy clear in the tests.
1420 const std::vector<uint8_t> initialBufferData(readbackSize, 0u);
1421 slot.buffer =
1422 utils::CreateBufferFromData(device, initialBufferData.data(), readbackSize,
1423 wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst);
Corentin Wallezeaae7462017-06-16 18:34:35 -04001424
1425 ReadbackReservation reservation;
Corentin Wallezaa7109c2018-10-25 10:42:49 +00001426 reservation.buffer = slot.buffer;
Corentin Wallezd5d77af2017-11-23 11:51:16 -08001427 reservation.slot = mReadbackSlots.size();
Corentin Wallezeaae7462017-06-16 18:34:35 -04001428 reservation.offset = 0;
1429
Corentin Wallezd5d77af2017-11-23 11:51:16 -08001430 mReadbackSlots.push_back(std::move(slot));
Corentin Wallezeaae7462017-06-16 18:34:35 -04001431 return reservation;
1432}
1433
Austin Engca0eac32019-08-28 23:18:10 +00001434void DawnTestBase::MapSlotsSynchronously() {
Corentin Walleza4da0322018-07-18 15:18:25 +02001435 // Initialize numPendingMapOperations before mapping, just in case the callback is called
1436 // immediately.
Corentin Wallezd5d77af2017-11-23 11:51:16 -08001437 mNumPendingMapOperations = mReadbackSlots.size();
Corentin Wallezeaae7462017-06-16 18:34:35 -04001438
1439 // Map all readback slots
Corentin Wallezd5d77af2017-11-23 11:51:16 -08001440 for (size_t i = 0; i < mReadbackSlots.size(); ++i) {
Corentin Wallez839053b2019-05-29 13:03:50 +00001441 MapReadUserdata* userdata = new MapReadUserdata{this, i};
Corentin Wallezeaae7462017-06-16 18:34:35 -04001442
Corentin Wallez2a232ba2020-07-16 16:35:40 +00001443 const ReadbackSlot& slot = mReadbackSlots[i];
Zhaoming Jiang2a5b9812021-10-18 05:30:39 +00001444 slot.buffer.MapAsync(wgpu::MapMode::Read, 0, wgpu::kWholeMapSize, SlotMapCallback,
1445 userdata);
Corentin Wallezeaae7462017-06-16 18:34:35 -04001446 }
1447
1448 // Busy wait until all map operations are done.
Corentin Wallezd5d77af2017-11-23 11:51:16 -08001449 while (mNumPendingMapOperations != 0) {
Corentin Wallez134e0802017-07-17 17:13:57 -04001450 WaitABit();
Corentin Wallezeaae7462017-06-16 18:34:35 -04001451 }
1452}
1453
1454// static
Corentin Wallez2a232ba2020-07-16 16:35:40 +00001455void DawnTestBase::SlotMapCallback(WGPUBufferMapAsyncStatus status, void* userdata_) {
Corentin Wallezcab352c2019-10-28 13:27:36 +00001456 DAWN_ASSERT(status == WGPUBufferMapAsyncStatus_Success);
Corentin Wallezeaae7462017-06-16 18:34:35 -04001457
Corentin Wallez2a232ba2020-07-16 16:35:40 +00001458 std::unique_ptr<MapReadUserdata> userdata(static_cast<MapReadUserdata*>(userdata_));
1459 DawnTestBase* test = userdata->test;
1460 ReadbackSlot* slot = &test->mReadbackSlots[userdata->slot];
Corentin Wallezeaae7462017-06-16 18:34:35 -04001461
Corentin Wallez2a232ba2020-07-16 16:35:40 +00001462 slot->mappedData = slot->buffer.GetConstMappedRange();
1463 test->mNumPendingMapOperations--;
Corentin Wallezeaae7462017-06-16 18:34:35 -04001464}
1465
Austin Engca0eac32019-08-28 23:18:10 +00001466void DawnTestBase::ResolveExpectations() {
Corentin Wallezd5d77af2017-11-23 11:51:16 -08001467 for (const auto& expectation : mDeferredExpectations) {
Corentin Wallez83a9c9d2018-07-18 13:37:54 +02001468 DAWN_ASSERT(mReadbackSlots[expectation.readbackSlot].mappedData != nullptr);
Corentin Wallezeaae7462017-06-16 18:34:35 -04001469
1470 // Get a pointer to the mapped copy of the data for the expectation.
Corentin Walleza4da0322018-07-18 15:18:25 +02001471 const char* data =
Rafael Cintronf54bb682019-05-03 00:58:27 +00001472 static_cast<const char*>(mReadbackSlots[expectation.readbackSlot].mappedData);
Corentin Wallezeaae7462017-06-16 18:34:35 -04001473 data += expectation.readbackOffset;
1474
Austin Eng51ff0132017-07-13 15:10:30 -04001475 uint32_t size;
1476 std::vector<char> packedData;
Corentin Wallezcdf2d8d2020-04-24 10:02:43 +00001477 if (expectation.rowBytes != expectation.bytesPerRow) {
1478 DAWN_ASSERT(expectation.bytesPerRow > expectation.rowBytes);
Corentin Walleza4da0322018-07-18 15:18:25 +02001479 uint32_t rowCount =
Corentin Wallezcdf2d8d2020-04-24 10:02:43 +00001480 (expectation.size + expectation.bytesPerRow - 1) / expectation.bytesPerRow;
Austin Eng51ff0132017-07-13 15:10:30 -04001481 uint32_t packedSize = rowCount * expectation.rowBytes;
1482 packedData.resize(packedSize);
1483 for (uint32_t r = 0; r < rowCount; ++r) {
1484 for (uint32_t i = 0; i < expectation.rowBytes; ++i) {
Corentin Wallezcdf2d8d2020-04-24 10:02:43 +00001485 packedData[i + r * expectation.rowBytes] =
1486 data[i + r * expectation.bytesPerRow];
Austin Eng51ff0132017-07-13 15:10:30 -04001487 }
1488 }
1489 data = packedData.data();
1490 size = packedSize;
1491 } else {
1492 size = expectation.size;
1493 }
1494
Corentin Wallezeaae7462017-06-16 18:34:35 -04001495 // Get the result for the expectation and add context to failures
Austin Eng51ff0132017-07-13 15:10:30 -04001496 testing::AssertionResult result = expectation.expectation->Check(data, size);
Corentin Wallezeaae7462017-06-16 18:34:35 -04001497 if (!result) {
Corentin Walleza4da0322018-07-18 15:18:25 +02001498 result << " Expectation created at " << expectation.file << ":" << expectation.line
1499 << std::endl;
Austin Eng4234c392017-07-17 09:37:08 -04001500 result << expectation.message->str();
Corentin Wallezeaae7462017-06-16 18:34:35 -04001501 }
1502
1503 EXPECT_TRUE(result);
1504 }
1505}
1506
Bryan Bernhart41b3f9c2020-11-20 20:38:37 +00001507std::unique_ptr<dawn_platform::Platform> DawnTestBase::CreateTestPlatform() {
1508 return nullptr;
1509}
1510
Corentin Wallez4cd65f02017-06-27 00:11:16 -04001511bool RGBA8::operator==(const RGBA8& other) const {
1512 return r == other.r && g == other.g && b == other.b && a == other.a;
1513}
1514
1515bool RGBA8::operator!=(const RGBA8& other) const {
1516 return !(*this == other);
1517}
1518
shrekshaof8c5e4a2020-12-24 03:11:17 +00001519bool RGBA8::operator<=(const RGBA8& other) const {
1520 return (r <= other.r && g <= other.g && b <= other.b && a <= other.a);
1521}
1522
1523bool RGBA8::operator>=(const RGBA8& other) const {
1524 return (r >= other.r && g >= other.g && b >= other.b && a >= other.a);
1525}
1526
Corentin Walleza4da0322018-07-18 15:18:25 +02001527std::ostream& operator<<(std::ostream& stream, const RGBA8& color) {
1528 return stream << "RGBA8(" << static_cast<int>(color.r) << ", " << static_cast<int>(color.g)
1529 << ", " << static_cast<int>(color.b) << ", " << static_cast<int>(color.a) << ")";
Corentin Wallez4cd65f02017-06-27 00:11:16 -04001530}
1531
Corentin Wallezeaae7462017-06-16 18:34:35 -04001532namespace detail {
Austin Engda722ad2020-05-15 20:28:05 +00001533 std::vector<AdapterTestParam> GetAvailableAdapterTestParamsForBackends(
1534 const BackendTestConfig* params,
1535 size_t numParams) {
Austin Eng25c747c2020-05-15 16:07:12 +00001536 ASSERT(gTestEnv != nullptr);
Austin Engda722ad2020-05-15 20:28:05 +00001537 return gTestEnv->GetAvailableAdapterTestParamsForBackends(params, numParams);
Corentin Wallezeaae7462017-06-16 18:34:35 -04001538 }
1539
1540 // Helper classes to set expectations
1541
shrekshaobdc029e2021-07-19 23:27:27 +00001542 template <typename T, typename U>
1543 ExpectEq<T, U>::ExpectEq(T singleValue, T tolerance) : mTolerance(tolerance) {
Corentin Wallezd5d77af2017-11-23 11:51:16 -08001544 mExpected.push_back(singleValue);
Corentin Wallezeaae7462017-06-16 18:34:35 -04001545 }
1546
shrekshaobdc029e2021-07-19 23:27:27 +00001547 template <typename T, typename U>
1548 ExpectEq<T, U>::ExpectEq(const T* values, const unsigned int count, T tolerance)
Austin Eng735d5042021-06-08 00:24:43 +00001549 : mTolerance(tolerance) {
Corentin Wallezd5d77af2017-11-23 11:51:16 -08001550 mExpected.assign(values, values + count);
Austin Eng49fe5662017-07-04 10:53:42 -04001551 }
1552
Austin Eng735d5042021-06-08 00:24:43 +00001553 namespace {
1554
shrekshaobdc029e2021-07-19 23:27:27 +00001555 template <typename T, typename U = T>
1556 testing::AssertionResult CheckImpl(const T& expected, const U& actual, const T& tolerance) {
Austin Eng735d5042021-06-08 00:24:43 +00001557 ASSERT(tolerance == T{});
1558 if (expected != actual) {
1559 return testing::AssertionFailure() << expected << ", actual " << actual;
1560 }
1561 return testing::AssertionSuccess();
1562 }
1563
1564 template <>
1565 testing::AssertionResult CheckImpl<float>(const float& expected,
1566 const float& actual,
1567 const float& tolerance) {
1568 if (abs(expected - actual) > tolerance) {
1569 return tolerance == 0.0
1570 ? testing::AssertionFailure() << expected << ", actual " << actual
1571 : testing::AssertionFailure() << "within " << tolerance << " of "
1572 << expected << ", actual " << actual;
1573 }
1574 return testing::AssertionSuccess();
1575 }
1576
shrekshaobdc029e2021-07-19 23:27:27 +00001577 // Interpret uint16_t as float16
1578 // This is mostly for reading float16 output from textures
1579 template <>
1580 testing::AssertionResult CheckImpl<float, uint16_t>(const float& expected,
1581 const uint16_t& actual,
1582 const float& tolerance) {
1583 float actualF32 = Float16ToFloat32(actual);
1584 if (abs(expected - actualF32) > tolerance) {
1585 return tolerance == 0.0
1586 ? testing::AssertionFailure() << expected << ", actual " << actualF32
1587 : testing::AssertionFailure() << "within " << tolerance << " of "
1588 << expected << ", actual " << actualF32;
1589 }
1590 return testing::AssertionSuccess();
1591 }
1592
Austin Eng735d5042021-06-08 00:24:43 +00001593 } // namespace
1594
shrekshaobdc029e2021-07-19 23:27:27 +00001595 template <typename T, typename U>
1596 testing::AssertionResult ExpectEq<T, U>::Check(const void* data, size_t size) {
1597 DAWN_ASSERT(size == sizeof(U) * mExpected.size());
1598 const U* actual = static_cast<const U*>(data);
Austin Eng1b8c64d2017-07-17 09:37:46 -04001599
Corentin Wallezd5d77af2017-11-23 11:51:16 -08001600 for (size_t i = 0; i < mExpected.size(); ++i) {
Austin Eng735d5042021-06-08 00:24:43 +00001601 testing::AssertionResult check = CheckImpl(mExpected[i], actual[i], mTolerance);
1602 if (!check) {
Corentin Walleza4da0322018-07-18 15:18:25 +02001603 testing::AssertionResult result = testing::AssertionFailure()
1604 << "Expected data[" << i << "] to be "
Austin Eng735d5042021-06-08 00:24:43 +00001605 << check.message() << std::endl;
Austin Eng1b8c64d2017-07-17 09:37:46 -04001606
Corentin Wallezd5d77af2017-11-23 11:51:16 -08001607 if (mExpected.size() <= 1024) {
Austin Eng1b8c64d2017-07-17 09:37:46 -04001608 result << "Expected:" << std::endl;
shrekshaof8c5e4a2020-12-24 03:11:17 +00001609 printBuffer(result, mExpected.data(), mExpected.size());
Austin Eng1b8c64d2017-07-17 09:37:46 -04001610
1611 result << "Actual:" << std::endl;
shrekshaof8c5e4a2020-12-24 03:11:17 +00001612 printBuffer(result, actual, mExpected.size());
Austin Eng1b8c64d2017-07-17 09:37:46 -04001613 }
1614
1615 return result;
Corentin Wallezeaae7462017-06-16 18:34:35 -04001616 }
1617 }
Corentin Wallezeaae7462017-06-16 18:34:35 -04001618 return testing::AssertionSuccess();
1619 }
1620
Stephen Whitee5ae3272018-02-04 11:07:02 -05001621 template class ExpectEq<uint8_t>;
Xinghua Caodb8f8042020-06-08 12:18:21 +00001622 template class ExpectEq<uint16_t>;
Corentin Wallezeaae7462017-06-16 18:34:35 -04001623 template class ExpectEq<uint32_t>;
Hao Lic0acb252020-08-04 06:41:56 +00001624 template class ExpectEq<uint64_t>;
Corentin Wallez4cd65f02017-06-27 00:11:16 -04001625 template class ExpectEq<RGBA8>;
Austin Eng0d661982020-01-16 00:12:10 +00001626 template class ExpectEq<float>;
shrekshaobdc029e2021-07-19 23:27:27 +00001627 template class ExpectEq<float, uint16_t>;
shrekshaof8c5e4a2020-12-24 03:11:17 +00001628
1629 template <typename T>
1630 ExpectBetweenColors<T>::ExpectBetweenColors(T value0, T value1) {
1631 T l, h;
1632 l.r = std::min(value0.r, value1.r);
1633 l.g = std::min(value0.g, value1.g);
1634 l.b = std::min(value0.b, value1.b);
1635 l.a = std::min(value0.a, value1.a);
1636
1637 h.r = std::max(value0.r, value1.r);
1638 h.g = std::max(value0.g, value1.g);
1639 h.b = std::max(value0.b, value1.b);
1640 h.a = std::max(value0.a, value1.a);
1641
1642 mLowerColorChannels.push_back(l);
1643 mHigherColorChannels.push_back(h);
1644
1645 mValues0.push_back(value0);
1646 mValues1.push_back(value1);
1647 }
1648
1649 template <typename T>
1650 testing::AssertionResult ExpectBetweenColors<T>::Check(const void* data, size_t size) {
1651 DAWN_ASSERT(size == sizeof(T) * mLowerColorChannels.size());
1652 DAWN_ASSERT(mHigherColorChannels.size() == mLowerColorChannels.size());
1653 DAWN_ASSERT(mValues0.size() == mValues1.size());
1654 DAWN_ASSERT(mValues0.size() == mLowerColorChannels.size());
1655
1656 const T* actual = static_cast<const T*>(data);
1657
1658 for (size_t i = 0; i < mLowerColorChannels.size(); ++i) {
1659 if (!(actual[i] >= mLowerColorChannels[i] && actual[i] <= mHigherColorChannels[i])) {
1660 testing::AssertionResult result = testing::AssertionFailure()
1661 << "Expected data[" << i << "] to be between "
1662 << mValues0[i] << " and " << mValues1[i]
1663 << ", actual " << actual[i] << std::endl;
1664
1665 if (mLowerColorChannels.size() <= 1024) {
1666 result << "Expected between:" << std::endl;
1667 printBuffer(result, mValues0.data(), mLowerColorChannels.size());
1668 result << "and" << std::endl;
1669 printBuffer(result, mValues1.data(), mLowerColorChannels.size());
1670
1671 result << "Actual:" << std::endl;
1672 printBuffer(result, actual, mLowerColorChannels.size());
1673 }
1674
1675 return result;
1676 }
1677 }
1678
1679 return testing::AssertionSuccess();
1680 }
1681
1682 template class ExpectBetweenColors<RGBA8>;
Corentin Walleza4da0322018-07-18 15:18:25 +02001683} // namespace detail