1cb93a386Sopenharmony_ci// Copyright 2017 The Dawn Authors 2cb93a386Sopenharmony_ci// 3cb93a386Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4cb93a386Sopenharmony_ci// you may not use this file except in compliance with the License. 5cb93a386Sopenharmony_ci// You may obtain a copy of the License at 6cb93a386Sopenharmony_ci// 7cb93a386Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8cb93a386Sopenharmony_ci// 9cb93a386Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10cb93a386Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11cb93a386Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12cb93a386Sopenharmony_ci// See the License for the specific language governing permissions and 13cb93a386Sopenharmony_ci// limitations under the License. 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci#include "tests/DawnTest.h" 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_ci#include "common/Assert.h" 18cb93a386Sopenharmony_ci#include "common/GPUInfo.h" 19cb93a386Sopenharmony_ci#include "common/Log.h" 20cb93a386Sopenharmony_ci#include "common/Math.h" 21cb93a386Sopenharmony_ci#include "common/Platform.h" 22cb93a386Sopenharmony_ci#include "common/SystemUtils.h" 23cb93a386Sopenharmony_ci#include "dawn/dawn_proc.h" 24cb93a386Sopenharmony_ci#include "dawn_wire/WireClient.h" 25cb93a386Sopenharmony_ci#include "dawn_wire/WireServer.h" 26cb93a386Sopenharmony_ci#include "utils/ComboRenderPipelineDescriptor.h" 27cb93a386Sopenharmony_ci#include "utils/PlatformDebugLogger.h" 28cb93a386Sopenharmony_ci#include "utils/SystemUtils.h" 29cb93a386Sopenharmony_ci#include "utils/TerribleCommandBuffer.h" 30cb93a386Sopenharmony_ci#include "utils/TestUtils.h" 31cb93a386Sopenharmony_ci#include "utils/WGPUHelpers.h" 32cb93a386Sopenharmony_ci#include "utils/WireHelper.h" 33cb93a386Sopenharmony_ci 34cb93a386Sopenharmony_ci#include <algorithm> 35cb93a386Sopenharmony_ci#include <fstream> 36cb93a386Sopenharmony_ci#include <iomanip> 37cb93a386Sopenharmony_ci#include <regex> 38cb93a386Sopenharmony_ci#include <sstream> 39cb93a386Sopenharmony_ci#include <unordered_map> 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_ci#if defined(DAWN_ENABLE_BACKEND_OPENGL) 42cb93a386Sopenharmony_ci# include "GLFW/glfw3.h" 43cb93a386Sopenharmony_ci# include "dawn_native/OpenGLBackend.h" 44cb93a386Sopenharmony_ci#endif // DAWN_ENABLE_BACKEND_OPENGL 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_cinamespace { 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_ci std::string ParamName(wgpu::BackendType type) { 49cb93a386Sopenharmony_ci switch (type) { 50cb93a386Sopenharmony_ci case wgpu::BackendType::D3D12: 51cb93a386Sopenharmony_ci return "D3D12"; 52cb93a386Sopenharmony_ci case wgpu::BackendType::Metal: 53cb93a386Sopenharmony_ci return "Metal"; 54cb93a386Sopenharmony_ci case wgpu::BackendType::Null: 55cb93a386Sopenharmony_ci return "Null"; 56cb93a386Sopenharmony_ci case wgpu::BackendType::OpenGL: 57cb93a386Sopenharmony_ci return "OpenGL"; 58cb93a386Sopenharmony_ci case wgpu::BackendType::OpenGLES: 59cb93a386Sopenharmony_ci return "OpenGLES"; 60cb93a386Sopenharmony_ci case wgpu::BackendType::Vulkan: 61cb93a386Sopenharmony_ci return "Vulkan"; 62cb93a386Sopenharmony_ci default: 63cb93a386Sopenharmony_ci UNREACHABLE(); 64cb93a386Sopenharmony_ci } 65cb93a386Sopenharmony_ci } 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ci const char* AdapterTypeName(wgpu::AdapterType type) { 68cb93a386Sopenharmony_ci switch (type) { 69cb93a386Sopenharmony_ci case wgpu::AdapterType::DiscreteGPU: 70cb93a386Sopenharmony_ci return "Discrete GPU"; 71cb93a386Sopenharmony_ci case wgpu::AdapterType::IntegratedGPU: 72cb93a386Sopenharmony_ci return "Integrated GPU"; 73cb93a386Sopenharmony_ci case wgpu::AdapterType::CPU: 74cb93a386Sopenharmony_ci return "CPU"; 75cb93a386Sopenharmony_ci case wgpu::AdapterType::Unknown: 76cb93a386Sopenharmony_ci return "Unknown"; 77cb93a386Sopenharmony_ci default: 78cb93a386Sopenharmony_ci UNREACHABLE(); 79cb93a386Sopenharmony_ci } 80cb93a386Sopenharmony_ci } 81cb93a386Sopenharmony_ci 82cb93a386Sopenharmony_ci struct MapReadUserdata { 83cb93a386Sopenharmony_ci DawnTestBase* test; 84cb93a386Sopenharmony_ci size_t slot; 85cb93a386Sopenharmony_ci }; 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_ci DawnTestEnvironment* gTestEnv = nullptr; 88cb93a386Sopenharmony_ci 89cb93a386Sopenharmony_ci template <typename T> 90cb93a386Sopenharmony_ci void printBuffer(testing::AssertionResult& result, const T* buffer, const size_t count) { 91cb93a386Sopenharmony_ci static constexpr unsigned int kBytes = sizeof(T); 92cb93a386Sopenharmony_ci 93cb93a386Sopenharmony_ci for (size_t index = 0; index < count; ++index) { 94cb93a386Sopenharmony_ci auto byteView = reinterpret_cast<const uint8_t*>(buffer + index); 95cb93a386Sopenharmony_ci for (unsigned int b = 0; b < kBytes; ++b) { 96cb93a386Sopenharmony_ci char buf[4]; 97cb93a386Sopenharmony_ci sprintf(buf, "%02X ", byteView[b]); 98cb93a386Sopenharmony_ci result << buf; 99cb93a386Sopenharmony_ci } 100cb93a386Sopenharmony_ci } 101cb93a386Sopenharmony_ci result << std::endl; 102cb93a386Sopenharmony_ci } 103cb93a386Sopenharmony_ci 104cb93a386Sopenharmony_ci} // anonymous namespace 105cb93a386Sopenharmony_ci 106cb93a386Sopenharmony_ciconst RGBA8 RGBA8::kZero = RGBA8(0, 0, 0, 0); 107cb93a386Sopenharmony_ciconst RGBA8 RGBA8::kBlack = RGBA8(0, 0, 0, 255); 108cb93a386Sopenharmony_ciconst RGBA8 RGBA8::kRed = RGBA8(255, 0, 0, 255); 109cb93a386Sopenharmony_ciconst RGBA8 RGBA8::kGreen = RGBA8(0, 255, 0, 255); 110cb93a386Sopenharmony_ciconst RGBA8 RGBA8::kBlue = RGBA8(0, 0, 255, 255); 111cb93a386Sopenharmony_ciconst RGBA8 RGBA8::kYellow = RGBA8(255, 255, 0, 255); 112cb93a386Sopenharmony_ciconst RGBA8 RGBA8::kWhite = RGBA8(255, 255, 255, 255); 113cb93a386Sopenharmony_ci 114cb93a386Sopenharmony_ciBackendTestConfig::BackendTestConfig(wgpu::BackendType backendType, 115cb93a386Sopenharmony_ci std::initializer_list<const char*> forceEnabledWorkarounds, 116cb93a386Sopenharmony_ci std::initializer_list<const char*> forceDisabledWorkarounds) 117cb93a386Sopenharmony_ci : backendType(backendType), 118cb93a386Sopenharmony_ci forceEnabledWorkarounds(forceEnabledWorkarounds), 119cb93a386Sopenharmony_ci forceDisabledWorkarounds(forceDisabledWorkarounds) { 120cb93a386Sopenharmony_ci} 121cb93a386Sopenharmony_ci 122cb93a386Sopenharmony_ciBackendTestConfig D3D12Backend(std::initializer_list<const char*> forceEnabledWorkarounds, 123cb93a386Sopenharmony_ci std::initializer_list<const char*> forceDisabledWorkarounds) { 124cb93a386Sopenharmony_ci return BackendTestConfig(wgpu::BackendType::D3D12, forceEnabledWorkarounds, 125cb93a386Sopenharmony_ci forceDisabledWorkarounds); 126cb93a386Sopenharmony_ci} 127cb93a386Sopenharmony_ci 128cb93a386Sopenharmony_ciBackendTestConfig MetalBackend(std::initializer_list<const char*> forceEnabledWorkarounds, 129cb93a386Sopenharmony_ci std::initializer_list<const char*> forceDisabledWorkarounds) { 130cb93a386Sopenharmony_ci return BackendTestConfig(wgpu::BackendType::Metal, forceEnabledWorkarounds, 131cb93a386Sopenharmony_ci forceDisabledWorkarounds); 132cb93a386Sopenharmony_ci} 133cb93a386Sopenharmony_ci 134cb93a386Sopenharmony_ciBackendTestConfig NullBackend(std::initializer_list<const char*> forceEnabledWorkarounds, 135cb93a386Sopenharmony_ci std::initializer_list<const char*> forceDisabledWorkarounds) { 136cb93a386Sopenharmony_ci return BackendTestConfig(wgpu::BackendType::Null, forceEnabledWorkarounds, 137cb93a386Sopenharmony_ci forceDisabledWorkarounds); 138cb93a386Sopenharmony_ci} 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_ciBackendTestConfig OpenGLBackend(std::initializer_list<const char*> forceEnabledWorkarounds, 141cb93a386Sopenharmony_ci std::initializer_list<const char*> forceDisabledWorkarounds) { 142cb93a386Sopenharmony_ci return BackendTestConfig(wgpu::BackendType::OpenGL, forceEnabledWorkarounds, 143cb93a386Sopenharmony_ci forceDisabledWorkarounds); 144cb93a386Sopenharmony_ci} 145cb93a386Sopenharmony_ci 146cb93a386Sopenharmony_ciBackendTestConfig OpenGLESBackend(std::initializer_list<const char*> forceEnabledWorkarounds, 147cb93a386Sopenharmony_ci std::initializer_list<const char*> forceDisabledWorkarounds) { 148cb93a386Sopenharmony_ci return BackendTestConfig(wgpu::BackendType::OpenGLES, forceEnabledWorkarounds, 149cb93a386Sopenharmony_ci forceDisabledWorkarounds); 150cb93a386Sopenharmony_ci} 151cb93a386Sopenharmony_ci 152cb93a386Sopenharmony_ciBackendTestConfig VulkanBackend(std::initializer_list<const char*> forceEnabledWorkarounds, 153cb93a386Sopenharmony_ci std::initializer_list<const char*> forceDisabledWorkarounds) { 154cb93a386Sopenharmony_ci return BackendTestConfig(wgpu::BackendType::Vulkan, forceEnabledWorkarounds, 155cb93a386Sopenharmony_ci forceDisabledWorkarounds); 156cb93a386Sopenharmony_ci} 157cb93a386Sopenharmony_ci 158cb93a386Sopenharmony_ciTestAdapterProperties::TestAdapterProperties(const wgpu::AdapterProperties& properties, 159cb93a386Sopenharmony_ci bool selected) 160cb93a386Sopenharmony_ci : wgpu::AdapterProperties(properties), adapterName(properties.name), selected(selected) { 161cb93a386Sopenharmony_ci} 162cb93a386Sopenharmony_ci 163cb93a386Sopenharmony_ciAdapterTestParam::AdapterTestParam(const BackendTestConfig& config, 164cb93a386Sopenharmony_ci const TestAdapterProperties& adapterProperties) 165cb93a386Sopenharmony_ci : adapterProperties(adapterProperties), 166cb93a386Sopenharmony_ci forceEnabledWorkarounds(config.forceEnabledWorkarounds), 167cb93a386Sopenharmony_ci forceDisabledWorkarounds(config.forceDisabledWorkarounds) { 168cb93a386Sopenharmony_ci} 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const AdapterTestParam& param) { 171cb93a386Sopenharmony_ci os << ParamName(param.adapterProperties.backendType) << " " 172cb93a386Sopenharmony_ci << param.adapterProperties.adapterName; 173cb93a386Sopenharmony_ci 174cb93a386Sopenharmony_ci // In a Windows Remote Desktop session there are two adapters named "Microsoft Basic Render 175cb93a386Sopenharmony_ci // Driver" with different adapter types. We must differentiate them to avoid any tests using the 176cb93a386Sopenharmony_ci // same name. 177cb93a386Sopenharmony_ci if (param.adapterProperties.deviceID == 0x008C) { 178cb93a386Sopenharmony_ci std::string adapterType = AdapterTypeName(param.adapterProperties.adapterType); 179cb93a386Sopenharmony_ci os << " " << adapterType; 180cb93a386Sopenharmony_ci } 181cb93a386Sopenharmony_ci 182cb93a386Sopenharmony_ci for (const char* forceEnabledWorkaround : param.forceEnabledWorkarounds) { 183cb93a386Sopenharmony_ci os << "; e:" << forceEnabledWorkaround; 184cb93a386Sopenharmony_ci } 185cb93a386Sopenharmony_ci for (const char* forceDisabledWorkaround : param.forceDisabledWorkarounds) { 186cb93a386Sopenharmony_ci os << "; d:" << forceDisabledWorkaround; 187cb93a386Sopenharmony_ci } 188cb93a386Sopenharmony_ci return os; 189cb93a386Sopenharmony_ci} 190cb93a386Sopenharmony_ci 191cb93a386Sopenharmony_ciDawnTestBase::PrintToStringParamName::PrintToStringParamName(const char* test) : mTest(test) { 192cb93a386Sopenharmony_ci} 193cb93a386Sopenharmony_ci 194cb93a386Sopenharmony_cistd::string DawnTestBase::PrintToStringParamName::SanitizeParamName(std::string paramName, 195cb93a386Sopenharmony_ci size_t index) const { 196cb93a386Sopenharmony_ci // Sanitize the adapter name for GoogleTest 197cb93a386Sopenharmony_ci std::string sanitizedName = std::regex_replace(paramName, std::regex("[^a-zA-Z0-9]+"), "_"); 198cb93a386Sopenharmony_ci 199cb93a386Sopenharmony_ci // Strip trailing underscores, if any. 200cb93a386Sopenharmony_ci while (sanitizedName.back() == '_') { 201cb93a386Sopenharmony_ci sanitizedName.resize(sanitizedName.length() - 1); 202cb93a386Sopenharmony_ci } 203cb93a386Sopenharmony_ci 204cb93a386Sopenharmony_ci // We don't know the the test name at this point, but the format usually looks like 205cb93a386Sopenharmony_ci // this. 206cb93a386Sopenharmony_ci std::string prefix = mTest + ".TheTestNameUsuallyGoesHere/"; 207cb93a386Sopenharmony_ci std::string testFormat = prefix + sanitizedName; 208cb93a386Sopenharmony_ci if (testFormat.length() > 220) { 209cb93a386Sopenharmony_ci // The bots don't support test names longer than 256. Shorten the name and append a unique 210cb93a386Sopenharmony_ci // index if we're close. The failure log will still print the full param name. 211cb93a386Sopenharmony_ci std::string suffix = std::string("__") + std::to_string(index); 212cb93a386Sopenharmony_ci size_t targetLength = sanitizedName.length(); 213cb93a386Sopenharmony_ci targetLength -= testFormat.length() - 220; 214cb93a386Sopenharmony_ci targetLength -= suffix.length(); 215cb93a386Sopenharmony_ci sanitizedName.resize(targetLength); 216cb93a386Sopenharmony_ci sanitizedName = sanitizedName + suffix; 217cb93a386Sopenharmony_ci } 218cb93a386Sopenharmony_ci return sanitizedName; 219cb93a386Sopenharmony_ci} 220cb93a386Sopenharmony_ci 221cb93a386Sopenharmony_ci// Implementation of DawnTestEnvironment 222cb93a386Sopenharmony_ci 223cb93a386Sopenharmony_civoid InitDawnEnd2EndTestEnvironment(int argc, char** argv) { 224cb93a386Sopenharmony_ci gTestEnv = new DawnTestEnvironment(argc, argv); 225cb93a386Sopenharmony_ci testing::AddGlobalTestEnvironment(gTestEnv); 226cb93a386Sopenharmony_ci} 227cb93a386Sopenharmony_ci 228cb93a386Sopenharmony_ci// static 229cb93a386Sopenharmony_civoid DawnTestEnvironment::SetEnvironment(DawnTestEnvironment* env) { 230cb93a386Sopenharmony_ci gTestEnv = env; 231cb93a386Sopenharmony_ci} 232cb93a386Sopenharmony_ci 233cb93a386Sopenharmony_ciDawnTestEnvironment::DawnTestEnvironment(int argc, char** argv) { 234cb93a386Sopenharmony_ci ParseArgs(argc, argv); 235cb93a386Sopenharmony_ci 236cb93a386Sopenharmony_ci if (mBackendValidationLevel != dawn_native::BackendValidationLevel::Disabled) { 237cb93a386Sopenharmony_ci mPlatformDebugLogger = 238cb93a386Sopenharmony_ci std::unique_ptr<utils::PlatformDebugLogger>(utils::CreatePlatformDebugLogger()); 239cb93a386Sopenharmony_ci } 240cb93a386Sopenharmony_ci 241cb93a386Sopenharmony_ci // Create a temporary instance to select available and preferred adapters. This is done before 242cb93a386Sopenharmony_ci // test instantiation so GetAvailableAdapterTestParamsForBackends can generate test 243cb93a386Sopenharmony_ci // parameterizations all selected adapters. We drop the instance at the end of this function 244cb93a386Sopenharmony_ci // because the Vulkan validation layers use static global mutexes which behave badly when 245cb93a386Sopenharmony_ci // Chromium's test launcher forks the test process. The instance will be recreated on test 246cb93a386Sopenharmony_ci // environment setup. 247cb93a386Sopenharmony_ci std::unique_ptr<dawn_native::Instance> instance = CreateInstanceAndDiscoverAdapters(); 248cb93a386Sopenharmony_ci ASSERT(instance); 249cb93a386Sopenharmony_ci 250cb93a386Sopenharmony_ci SelectPreferredAdapterProperties(instance.get()); 251cb93a386Sopenharmony_ci PrintTestConfigurationAndAdapterInfo(instance.get()); 252cb93a386Sopenharmony_ci} 253cb93a386Sopenharmony_ci 254cb93a386Sopenharmony_ciDawnTestEnvironment::~DawnTestEnvironment() = default; 255cb93a386Sopenharmony_ci 256cb93a386Sopenharmony_civoid DawnTestEnvironment::ParseArgs(int argc, char** argv) { 257cb93a386Sopenharmony_ci size_t argLen = 0; // Set when parsing --arg=X arguments 258cb93a386Sopenharmony_ci for (int i = 1; i < argc; ++i) { 259cb93a386Sopenharmony_ci if (strcmp("-w", argv[i]) == 0 || strcmp("--use-wire", argv[i]) == 0) { 260cb93a386Sopenharmony_ci mUseWire = true; 261cb93a386Sopenharmony_ci continue; 262cb93a386Sopenharmony_ci } 263cb93a386Sopenharmony_ci 264cb93a386Sopenharmony_ci if (strcmp("--run-suppressed-tests", argv[i]) == 0) { 265cb93a386Sopenharmony_ci mRunSuppressedTests = true; 266cb93a386Sopenharmony_ci continue; 267cb93a386Sopenharmony_ci } 268cb93a386Sopenharmony_ci 269cb93a386Sopenharmony_ci constexpr const char kEnableBackendValidationSwitch[] = "--enable-backend-validation"; 270cb93a386Sopenharmony_ci argLen = sizeof(kEnableBackendValidationSwitch) - 1; 271cb93a386Sopenharmony_ci if (strncmp(argv[i], kEnableBackendValidationSwitch, argLen) == 0) { 272cb93a386Sopenharmony_ci const char* level = argv[i] + argLen; 273cb93a386Sopenharmony_ci if (level[0] != '\0') { 274cb93a386Sopenharmony_ci if (strcmp(level, "=full") == 0) { 275cb93a386Sopenharmony_ci mBackendValidationLevel = dawn_native::BackendValidationLevel::Full; 276cb93a386Sopenharmony_ci } else if (strcmp(level, "=partial") == 0) { 277cb93a386Sopenharmony_ci mBackendValidationLevel = dawn_native::BackendValidationLevel::Partial; 278cb93a386Sopenharmony_ci } else if (strcmp(level, "=disabled") == 0) { 279cb93a386Sopenharmony_ci mBackendValidationLevel = dawn_native::BackendValidationLevel::Disabled; 280cb93a386Sopenharmony_ci } else { 281cb93a386Sopenharmony_ci dawn::ErrorLog() << "Invalid backend validation level" << level; 282cb93a386Sopenharmony_ci UNREACHABLE(); 283cb93a386Sopenharmony_ci } 284cb93a386Sopenharmony_ci } else { 285cb93a386Sopenharmony_ci mBackendValidationLevel = dawn_native::BackendValidationLevel::Partial; 286cb93a386Sopenharmony_ci } 287cb93a386Sopenharmony_ci continue; 288cb93a386Sopenharmony_ci } 289cb93a386Sopenharmony_ci 290cb93a386Sopenharmony_ci if (strcmp("-c", argv[i]) == 0 || strcmp("--begin-capture-on-startup", argv[i]) == 0) { 291cb93a386Sopenharmony_ci mBeginCaptureOnStartup = true; 292cb93a386Sopenharmony_ci continue; 293cb93a386Sopenharmony_ci } 294cb93a386Sopenharmony_ci 295cb93a386Sopenharmony_ci if (mToggleParser.ParseEnabledToggles(argv[i])) { 296cb93a386Sopenharmony_ci continue; 297cb93a386Sopenharmony_ci } 298cb93a386Sopenharmony_ci 299cb93a386Sopenharmony_ci if (mToggleParser.ParseDisabledToggles(argv[i])) { 300cb93a386Sopenharmony_ci continue; 301cb93a386Sopenharmony_ci } 302cb93a386Sopenharmony_ci 303cb93a386Sopenharmony_ci constexpr const char kVendorIdFilterArg[] = "--adapter-vendor-id="; 304cb93a386Sopenharmony_ci argLen = sizeof(kVendorIdFilterArg) - 1; 305cb93a386Sopenharmony_ci if (strncmp(argv[i], kVendorIdFilterArg, argLen) == 0) { 306cb93a386Sopenharmony_ci const char* vendorIdFilter = argv[i] + argLen; 307cb93a386Sopenharmony_ci if (vendorIdFilter[0] != '\0') { 308cb93a386Sopenharmony_ci mVendorIdFilter = strtoul(vendorIdFilter, nullptr, 16); 309cb93a386Sopenharmony_ci // Set filter flag if vendor id is non-zero. 310cb93a386Sopenharmony_ci mHasVendorIdFilter = mVendorIdFilter != 0; 311cb93a386Sopenharmony_ci } 312cb93a386Sopenharmony_ci continue; 313cb93a386Sopenharmony_ci } 314cb93a386Sopenharmony_ci 315cb93a386Sopenharmony_ci constexpr const char kExclusiveDeviceTypePreferenceArg[] = 316cb93a386Sopenharmony_ci "--exclusive-device-type-preference="; 317cb93a386Sopenharmony_ci argLen = sizeof(kExclusiveDeviceTypePreferenceArg) - 1; 318cb93a386Sopenharmony_ci if (strncmp(argv[i], kExclusiveDeviceTypePreferenceArg, argLen) == 0) { 319cb93a386Sopenharmony_ci const char* preference = argv[i] + argLen; 320cb93a386Sopenharmony_ci if (preference[0] != '\0') { 321cb93a386Sopenharmony_ci std::istringstream ss(preference); 322cb93a386Sopenharmony_ci std::string type; 323cb93a386Sopenharmony_ci while (std::getline(ss, type, ',')) { 324cb93a386Sopenharmony_ci if (strcmp(type.c_str(), "discrete") == 0) { 325cb93a386Sopenharmony_ci mDevicePreferences.push_back(dawn_native::DeviceType::DiscreteGPU); 326cb93a386Sopenharmony_ci } else if (strcmp(type.c_str(), "integrated") == 0) { 327cb93a386Sopenharmony_ci mDevicePreferences.push_back(dawn_native::DeviceType::IntegratedGPU); 328cb93a386Sopenharmony_ci } else if (strcmp(type.c_str(), "cpu") == 0) { 329cb93a386Sopenharmony_ci mDevicePreferences.push_back(dawn_native::DeviceType::CPU); 330cb93a386Sopenharmony_ci } else { 331cb93a386Sopenharmony_ci dawn::ErrorLog() << "Invalid device type preference: " << type; 332cb93a386Sopenharmony_ci UNREACHABLE(); 333cb93a386Sopenharmony_ci } 334cb93a386Sopenharmony_ci } 335cb93a386Sopenharmony_ci } 336cb93a386Sopenharmony_ci continue; 337cb93a386Sopenharmony_ci } 338cb93a386Sopenharmony_ci 339cb93a386Sopenharmony_ci constexpr const char kWireTraceDirArg[] = "--wire-trace-dir="; 340cb93a386Sopenharmony_ci argLen = sizeof(kWireTraceDirArg) - 1; 341cb93a386Sopenharmony_ci if (strncmp(argv[i], kWireTraceDirArg, argLen) == 0) { 342cb93a386Sopenharmony_ci mWireTraceDir = argv[i] + argLen; 343cb93a386Sopenharmony_ci continue; 344cb93a386Sopenharmony_ci } 345cb93a386Sopenharmony_ci 346cb93a386Sopenharmony_ci constexpr const char kBackendArg[] = "--backend="; 347cb93a386Sopenharmony_ci argLen = sizeof(kBackendArg) - 1; 348cb93a386Sopenharmony_ci if (strncmp(argv[i], kBackendArg, argLen) == 0) { 349cb93a386Sopenharmony_ci const char* param = argv[i] + argLen; 350cb93a386Sopenharmony_ci if (strcmp("d3d12", param) == 0) { 351cb93a386Sopenharmony_ci mBackendTypeFilter = wgpu::BackendType::D3D12; 352cb93a386Sopenharmony_ci } else if (strcmp("metal", param) == 0) { 353cb93a386Sopenharmony_ci mBackendTypeFilter = wgpu::BackendType::Metal; 354cb93a386Sopenharmony_ci } else if (strcmp("null", param) == 0) { 355cb93a386Sopenharmony_ci mBackendTypeFilter = wgpu::BackendType::Null; 356cb93a386Sopenharmony_ci } else if (strcmp("opengl", param) == 0) { 357cb93a386Sopenharmony_ci mBackendTypeFilter = wgpu::BackendType::OpenGL; 358cb93a386Sopenharmony_ci } else if (strcmp("opengles", param) == 0) { 359cb93a386Sopenharmony_ci mBackendTypeFilter = wgpu::BackendType::OpenGLES; 360cb93a386Sopenharmony_ci } else if (strcmp("vulkan", param) == 0) { 361cb93a386Sopenharmony_ci mBackendTypeFilter = wgpu::BackendType::Vulkan; 362cb93a386Sopenharmony_ci } else { 363cb93a386Sopenharmony_ci dawn::ErrorLog() 364cb93a386Sopenharmony_ci << "Invalid backend \"" << param 365cb93a386Sopenharmony_ci << "\". Valid backends are: d3d12, metal, null, opengl, opengles, vulkan."; 366cb93a386Sopenharmony_ci UNREACHABLE(); 367cb93a386Sopenharmony_ci } 368cb93a386Sopenharmony_ci mHasBackendTypeFilter = true; 369cb93a386Sopenharmony_ci continue; 370cb93a386Sopenharmony_ci } 371cb93a386Sopenharmony_ci if (strcmp("-h", argv[i]) == 0 || strcmp("--help", argv[i]) == 0) { 372cb93a386Sopenharmony_ci dawn::InfoLog() 373cb93a386Sopenharmony_ci << "\n\nUsage: " << argv[0] 374cb93a386Sopenharmony_ci << " [GTEST_FLAGS...] [-w] [-c]\n" 375cb93a386Sopenharmony_ci " [--enable-toggles=toggles] [--disable-toggles=toggles]\n" 376cb93a386Sopenharmony_ci " [--backend=x]\n" 377cb93a386Sopenharmony_ci " [--adapter-vendor-id=x] " 378cb93a386Sopenharmony_ci "[--enable-backend-validation[=full,partial,disabled]]\n" 379cb93a386Sopenharmony_ci " [--exclusive-device-type-preference=integrated,cpu,discrete]\n\n" 380cb93a386Sopenharmony_ci " -w, --use-wire: Run the tests through the wire (defaults to no wire)\n" 381cb93a386Sopenharmony_ci " -c, --begin-capture-on-startup: Begin debug capture on startup " 382cb93a386Sopenharmony_ci "(defaults to no capture)\n" 383cb93a386Sopenharmony_ci " --enable-backend-validation: Enables backend validation. Defaults to \n" 384cb93a386Sopenharmony_ci " 'partial' to enable only minimum backend validation. Set to 'full' to\n" 385cb93a386Sopenharmony_ci " enable all available backend validation with less performance overhead.\n" 386cb93a386Sopenharmony_ci " Set to 'disabled' to run with no validation (same as no flag).\n" 387cb93a386Sopenharmony_ci " --enable-toggles: Comma-delimited list of Dawn toggles to enable.\n" 388cb93a386Sopenharmony_ci " ex.) skip_validation,disable_robustness,turn_off_vsync\n" 389cb93a386Sopenharmony_ci " --disable-toggles: Comma-delimited list of Dawn toggles to disable\n" 390cb93a386Sopenharmony_ci " --adapter-vendor-id: Select adapter by vendor id to run end2end tests" 391cb93a386Sopenharmony_ci "on multi-GPU systems \n" 392cb93a386Sopenharmony_ci " --backend: Select adapter by backend type. Valid backends are: d3d12, metal, " 393cb93a386Sopenharmony_ci "null, opengl, opengles, vulkan\n" 394cb93a386Sopenharmony_ci " --exclusive-device-type-preference: Comma-delimited list of preferred device " 395cb93a386Sopenharmony_ci "types. For each backend, tests will run only on adapters that match the first " 396cb93a386Sopenharmony_ci "available device type\n" 397cb93a386Sopenharmony_ci " --run-suppressed-tests: Run all the tests that will be skipped by the macro " 398cb93a386Sopenharmony_ci "DAWN_SUPPRESS_TEST_IF()\n"; 399cb93a386Sopenharmony_ci continue; 400cb93a386Sopenharmony_ci } 401cb93a386Sopenharmony_ci 402cb93a386Sopenharmony_ci // Skip over args that look like they're for Googletest. 403cb93a386Sopenharmony_ci constexpr const char kGtestArgPrefix[] = "--gtest_"; 404cb93a386Sopenharmony_ci if (strncmp(kGtestArgPrefix, argv[i], sizeof(kGtestArgPrefix) - 1) == 0) { 405cb93a386Sopenharmony_ci continue; 406cb93a386Sopenharmony_ci } 407cb93a386Sopenharmony_ci 408cb93a386Sopenharmony_ci dawn::WarningLog() << " Unused argument: " << argv[i]; 409cb93a386Sopenharmony_ci } 410cb93a386Sopenharmony_ci} 411cb93a386Sopenharmony_ci 412cb93a386Sopenharmony_cistd::unique_ptr<dawn_native::Instance> DawnTestEnvironment::CreateInstanceAndDiscoverAdapters() { 413cb93a386Sopenharmony_ci auto instance = std::make_unique<dawn_native::Instance>(); 414cb93a386Sopenharmony_ci instance->EnableBeginCaptureOnStartup(mBeginCaptureOnStartup); 415cb93a386Sopenharmony_ci instance->SetBackendValidationLevel(mBackendValidationLevel); 416cb93a386Sopenharmony_ci instance->DiscoverDefaultAdapters(); 417cb93a386Sopenharmony_ci 418cb93a386Sopenharmony_ci#ifdef DAWN_ENABLE_BACKEND_DESKTOP_GL 419cb93a386Sopenharmony_ci if (!glfwInit()) { 420cb93a386Sopenharmony_ci return instance; 421cb93a386Sopenharmony_ci } 422cb93a386Sopenharmony_ci glfwDefaultWindowHints(); 423cb93a386Sopenharmony_ci glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); 424cb93a386Sopenharmony_ci glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4); 425cb93a386Sopenharmony_ci glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); 426cb93a386Sopenharmony_ci glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 427cb93a386Sopenharmony_ci glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); 428cb93a386Sopenharmony_ci 429cb93a386Sopenharmony_ci mOpenGLWindow = glfwCreateWindow(400, 400, "Dawn OpenGL test window", nullptr, nullptr); 430cb93a386Sopenharmony_ci 431cb93a386Sopenharmony_ci glfwMakeContextCurrent(mOpenGLWindow); 432cb93a386Sopenharmony_ci dawn_native::opengl::AdapterDiscoveryOptions adapterOptions; 433cb93a386Sopenharmony_ci adapterOptions.getProc = reinterpret_cast<void* (*)(const char*)>(glfwGetProcAddress); 434cb93a386Sopenharmony_ci instance->DiscoverAdapters(&adapterOptions); 435cb93a386Sopenharmony_ci#endif // DAWN_ENABLE_BACKEND_DESKTOP_GL 436cb93a386Sopenharmony_ci 437cb93a386Sopenharmony_ci#ifdef DAWN_ENABLE_BACKEND_OPENGLES 438cb93a386Sopenharmony_ci 439cb93a386Sopenharmony_ci ScopedEnvironmentVar angleDefaultPlatform; 440cb93a386Sopenharmony_ci if (GetEnvironmentVar("ANGLE_DEFAULT_PLATFORM").first.empty()) { 441cb93a386Sopenharmony_ci angleDefaultPlatform.Set("ANGLE_DEFAULT_PLATFORM", "swiftshader"); 442cb93a386Sopenharmony_ci } 443cb93a386Sopenharmony_ci 444cb93a386Sopenharmony_ci if (!glfwInit()) { 445cb93a386Sopenharmony_ci return instance; 446cb93a386Sopenharmony_ci } 447cb93a386Sopenharmony_ci glfwDefaultWindowHints(); 448cb93a386Sopenharmony_ci glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 449cb93a386Sopenharmony_ci glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); 450cb93a386Sopenharmony_ci glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); 451cb93a386Sopenharmony_ci glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API); 452cb93a386Sopenharmony_ci glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); 453cb93a386Sopenharmony_ci 454cb93a386Sopenharmony_ci mOpenGLESWindow = glfwCreateWindow(400, 400, "Dawn OpenGLES test window", nullptr, nullptr); 455cb93a386Sopenharmony_ci 456cb93a386Sopenharmony_ci glfwMakeContextCurrent(mOpenGLESWindow); 457cb93a386Sopenharmony_ci dawn_native::opengl::AdapterDiscoveryOptionsES adapterOptionsES; 458cb93a386Sopenharmony_ci adapterOptionsES.getProc = reinterpret_cast<void* (*)(const char*)>(glfwGetProcAddress); 459cb93a386Sopenharmony_ci instance->DiscoverAdapters(&adapterOptionsES); 460cb93a386Sopenharmony_ci glfwWindowHint(GLFW_VISIBLE, GLFW_TRUE); 461cb93a386Sopenharmony_ci#endif // DAWN_ENABLE_BACKEND_OPENGLES 462cb93a386Sopenharmony_ci 463cb93a386Sopenharmony_ci return instance; 464cb93a386Sopenharmony_ci} 465cb93a386Sopenharmony_ci 466cb93a386Sopenharmony_ciGLFWwindow* DawnTestEnvironment::GetOpenGLWindow() const { 467cb93a386Sopenharmony_ci return mOpenGLWindow; 468cb93a386Sopenharmony_ci} 469cb93a386Sopenharmony_ci 470cb93a386Sopenharmony_ciGLFWwindow* DawnTestEnvironment::GetOpenGLESWindow() const { 471cb93a386Sopenharmony_ci return mOpenGLESWindow; 472cb93a386Sopenharmony_ci} 473cb93a386Sopenharmony_ci 474cb93a386Sopenharmony_civoid DawnTestEnvironment::SelectPreferredAdapterProperties(const dawn_native::Instance* instance) { 475cb93a386Sopenharmony_ci // Get the first available preferred device type. 476cb93a386Sopenharmony_ci dawn_native::DeviceType preferredDeviceType = static_cast<dawn_native::DeviceType>(-1); 477cb93a386Sopenharmony_ci bool hasDevicePreference = false; 478cb93a386Sopenharmony_ci for (dawn_native::DeviceType devicePreference : mDevicePreferences) { 479cb93a386Sopenharmony_ci for (const dawn_native::Adapter& adapter : instance->GetAdapters()) { 480cb93a386Sopenharmony_ci wgpu::AdapterProperties properties; 481cb93a386Sopenharmony_ci adapter.GetProperties(&properties); 482cb93a386Sopenharmony_ci 483cb93a386Sopenharmony_ci if (adapter.GetDeviceType() == devicePreference) { 484cb93a386Sopenharmony_ci preferredDeviceType = devicePreference; 485cb93a386Sopenharmony_ci hasDevicePreference = true; 486cb93a386Sopenharmony_ci break; 487cb93a386Sopenharmony_ci } 488cb93a386Sopenharmony_ci } 489cb93a386Sopenharmony_ci if (hasDevicePreference) { 490cb93a386Sopenharmony_ci break; 491cb93a386Sopenharmony_ci } 492cb93a386Sopenharmony_ci } 493cb93a386Sopenharmony_ci 494cb93a386Sopenharmony_ci std::set<std::pair<wgpu::BackendType, std::string>> adapterNameSet; 495cb93a386Sopenharmony_ci for (const dawn_native::Adapter& adapter : instance->GetAdapters()) { 496cb93a386Sopenharmony_ci wgpu::AdapterProperties properties; 497cb93a386Sopenharmony_ci adapter.GetProperties(&properties); 498cb93a386Sopenharmony_ci 499cb93a386Sopenharmony_ci // All adapters are selected by default. 500cb93a386Sopenharmony_ci bool selected = true; 501cb93a386Sopenharmony_ci // The adapter is deselected if: 502cb93a386Sopenharmony_ci if (mHasBackendTypeFilter) { 503cb93a386Sopenharmony_ci // It doesn't match the backend type, if present. 504cb93a386Sopenharmony_ci selected &= properties.backendType == mBackendTypeFilter; 505cb93a386Sopenharmony_ci } 506cb93a386Sopenharmony_ci if (mHasVendorIdFilter) { 507cb93a386Sopenharmony_ci // It doesn't match the vendor id, if present. 508cb93a386Sopenharmony_ci selected &= mVendorIdFilter == properties.vendorID; 509cb93a386Sopenharmony_ci 510cb93a386Sopenharmony_ci if (!mDevicePreferences.empty()) { 511cb93a386Sopenharmony_ci dawn::WarningLog() << "Vendor ID filter provided. Ignoring device type preference."; 512cb93a386Sopenharmony_ci } 513cb93a386Sopenharmony_ci } 514cb93a386Sopenharmony_ci if (hasDevicePreference) { 515cb93a386Sopenharmony_ci // There is a device preference and: 516cb93a386Sopenharmony_ci selected &= 517cb93a386Sopenharmony_ci // The device type doesn't match the first available preferred type for that 518cb93a386Sopenharmony_ci // backend, if present. 519cb93a386Sopenharmony_ci (adapter.GetDeviceType() == preferredDeviceType) || 520cb93a386Sopenharmony_ci // Always select Unknown OpenGL adapters if we don't want a CPU adapter. 521cb93a386Sopenharmony_ci // OpenGL will usually be unknown because we can't query the device type. 522cb93a386Sopenharmony_ci // If we ever have Swiftshader GL (unlikely), we could set the DeviceType properly. 523cb93a386Sopenharmony_ci (preferredDeviceType != dawn_native::DeviceType::CPU && 524cb93a386Sopenharmony_ci adapter.GetDeviceType() == dawn_native::DeviceType::Unknown && 525cb93a386Sopenharmony_ci (properties.backendType == wgpu::BackendType::OpenGL || 526cb93a386Sopenharmony_ci properties.backendType == wgpu::BackendType::OpenGLES)) || 527cb93a386Sopenharmony_ci // Always select the Null backend. There are few tests on this backend, and they run 528cb93a386Sopenharmony_ci // quickly. This is temporary as to not lose coverage. We can group it with 529cb93a386Sopenharmony_ci // Swiftshader as a CPU adapter when we have Swiftshader tests. 530cb93a386Sopenharmony_ci (properties.backendType == wgpu::BackendType::Null); 531cb93a386Sopenharmony_ci } 532cb93a386Sopenharmony_ci 533cb93a386Sopenharmony_ci // In Windows Remote Desktop sessions we may be able to discover multiple adapters that 534cb93a386Sopenharmony_ci // have the same name and backend type. We will just choose one adapter from them in our 535cb93a386Sopenharmony_ci // tests. 536cb93a386Sopenharmony_ci const auto adapterTypeAndName = 537cb93a386Sopenharmony_ci std::make_pair(properties.backendType, std::string(properties.name)); 538cb93a386Sopenharmony_ci if (adapterNameSet.find(adapterTypeAndName) == adapterNameSet.end()) { 539cb93a386Sopenharmony_ci adapterNameSet.insert(adapterTypeAndName); 540cb93a386Sopenharmony_ci mAdapterProperties.emplace_back(properties, selected); 541cb93a386Sopenharmony_ci } 542cb93a386Sopenharmony_ci } 543cb93a386Sopenharmony_ci} 544cb93a386Sopenharmony_ci 545cb93a386Sopenharmony_cistd::vector<AdapterTestParam> DawnTestEnvironment::GetAvailableAdapterTestParamsForBackends( 546cb93a386Sopenharmony_ci const BackendTestConfig* params, 547cb93a386Sopenharmony_ci size_t numParams) { 548cb93a386Sopenharmony_ci std::vector<AdapterTestParam> testParams; 549cb93a386Sopenharmony_ci for (size_t i = 0; i < numParams; ++i) { 550cb93a386Sopenharmony_ci for (const auto& adapterProperties : mAdapterProperties) { 551cb93a386Sopenharmony_ci if (params[i].backendType == adapterProperties.backendType && 552cb93a386Sopenharmony_ci adapterProperties.selected) { 553cb93a386Sopenharmony_ci testParams.push_back(AdapterTestParam(params[i], adapterProperties)); 554cb93a386Sopenharmony_ci } 555cb93a386Sopenharmony_ci } 556cb93a386Sopenharmony_ci } 557cb93a386Sopenharmony_ci return testParams; 558cb93a386Sopenharmony_ci} 559cb93a386Sopenharmony_ci 560cb93a386Sopenharmony_civoid DawnTestEnvironment::PrintTestConfigurationAndAdapterInfo( 561cb93a386Sopenharmony_ci dawn_native::Instance* instance) const { 562cb93a386Sopenharmony_ci dawn::LogMessage log = dawn::InfoLog(); 563cb93a386Sopenharmony_ci log << "Testing configuration\n" 564cb93a386Sopenharmony_ci "---------------------\n" 565cb93a386Sopenharmony_ci "UseWire: " 566cb93a386Sopenharmony_ci << (mUseWire ? "true" : "false") 567cb93a386Sopenharmony_ci << "\n" 568cb93a386Sopenharmony_ci "Run suppressed tests: " 569cb93a386Sopenharmony_ci << (mRunSuppressedTests ? "true" : "false") 570cb93a386Sopenharmony_ci << "\n" 571cb93a386Sopenharmony_ci "BackendValidation: "; 572cb93a386Sopenharmony_ci 573cb93a386Sopenharmony_ci switch (mBackendValidationLevel) { 574cb93a386Sopenharmony_ci case dawn_native::BackendValidationLevel::Full: 575cb93a386Sopenharmony_ci log << "full"; 576cb93a386Sopenharmony_ci break; 577cb93a386Sopenharmony_ci case dawn_native::BackendValidationLevel::Partial: 578cb93a386Sopenharmony_ci log << "partial"; 579cb93a386Sopenharmony_ci break; 580cb93a386Sopenharmony_ci case dawn_native::BackendValidationLevel::Disabled: 581cb93a386Sopenharmony_ci log << "disabled"; 582cb93a386Sopenharmony_ci break; 583cb93a386Sopenharmony_ci default: 584cb93a386Sopenharmony_ci UNREACHABLE(); 585cb93a386Sopenharmony_ci } 586cb93a386Sopenharmony_ci 587cb93a386Sopenharmony_ci if (GetEnabledToggles().size() > 0) { 588cb93a386Sopenharmony_ci log << "\n" 589cb93a386Sopenharmony_ci "Enabled Toggles\n"; 590cb93a386Sopenharmony_ci for (const std::string& toggle : GetEnabledToggles()) { 591cb93a386Sopenharmony_ci const dawn_native::ToggleInfo* info = instance->GetToggleInfo(toggle.c_str()); 592cb93a386Sopenharmony_ci ASSERT(info != nullptr); 593cb93a386Sopenharmony_ci log << " - " << info->name << ": " << info->description << "\n"; 594cb93a386Sopenharmony_ci } 595cb93a386Sopenharmony_ci } 596cb93a386Sopenharmony_ci 597cb93a386Sopenharmony_ci if (GetDisabledToggles().size() > 0) { 598cb93a386Sopenharmony_ci log << "\n" 599cb93a386Sopenharmony_ci "Disabled Toggles\n"; 600cb93a386Sopenharmony_ci for (const std::string& toggle : GetDisabledToggles()) { 601cb93a386Sopenharmony_ci const dawn_native::ToggleInfo* info = instance->GetToggleInfo(toggle.c_str()); 602cb93a386Sopenharmony_ci ASSERT(info != nullptr); 603cb93a386Sopenharmony_ci log << " - " << info->name << ": " << info->description << "\n"; 604cb93a386Sopenharmony_ci } 605cb93a386Sopenharmony_ci } 606cb93a386Sopenharmony_ci 607cb93a386Sopenharmony_ci log << "\n" 608cb93a386Sopenharmony_ci "BeginCaptureOnStartup: " 609cb93a386Sopenharmony_ci << (mBeginCaptureOnStartup ? "true" : "false") 610cb93a386Sopenharmony_ci << "\n" 611cb93a386Sopenharmony_ci "\n" 612cb93a386Sopenharmony_ci << "System adapters: \n"; 613cb93a386Sopenharmony_ci 614cb93a386Sopenharmony_ci for (const TestAdapterProperties& properties : mAdapterProperties) { 615cb93a386Sopenharmony_ci std::ostringstream vendorId; 616cb93a386Sopenharmony_ci std::ostringstream deviceId; 617cb93a386Sopenharmony_ci vendorId << std::setfill('0') << std::uppercase << std::internal << std::hex << std::setw(4) 618cb93a386Sopenharmony_ci << properties.vendorID; 619cb93a386Sopenharmony_ci deviceId << std::setfill('0') << std::uppercase << std::internal << std::hex << std::setw(4) 620cb93a386Sopenharmony_ci << properties.deviceID; 621cb93a386Sopenharmony_ci 622cb93a386Sopenharmony_ci // Preparing for outputting hex numbers 623cb93a386Sopenharmony_ci log << std::showbase << std::hex << std::setfill('0') << std::setw(4) 624cb93a386Sopenharmony_ci 625cb93a386Sopenharmony_ci << " - \"" << properties.adapterName << "\" - \"" << properties.driverDescription 626cb93a386Sopenharmony_ci << "\"\n" 627cb93a386Sopenharmony_ci << " type: " << AdapterTypeName(properties.adapterType) 628cb93a386Sopenharmony_ci << ", backend: " << ParamName(properties.backendType) << "\n" 629cb93a386Sopenharmony_ci << " vendorId: 0x" << vendorId.str() << ", deviceId: 0x" << deviceId.str() 630cb93a386Sopenharmony_ci << (properties.selected ? " [Selected]" : "") << "\n"; 631cb93a386Sopenharmony_ci } 632cb93a386Sopenharmony_ci} 633cb93a386Sopenharmony_ci 634cb93a386Sopenharmony_civoid DawnTestEnvironment::SetUp() { 635cb93a386Sopenharmony_ci mInstance = CreateInstanceAndDiscoverAdapters(); 636cb93a386Sopenharmony_ci ASSERT(mInstance); 637cb93a386Sopenharmony_ci} 638cb93a386Sopenharmony_ci 639cb93a386Sopenharmony_civoid DawnTestEnvironment::TearDown() { 640cb93a386Sopenharmony_ci // When Vulkan validation layers are enabled, it's unsafe to call Vulkan APIs in the destructor 641cb93a386Sopenharmony_ci // of a static/global variable, so the instance must be manually released beforehand. 642cb93a386Sopenharmony_ci mInstance.reset(); 643cb93a386Sopenharmony_ci} 644cb93a386Sopenharmony_ci 645cb93a386Sopenharmony_cibool DawnTestEnvironment::UsesWire() const { 646cb93a386Sopenharmony_ci return mUseWire; 647cb93a386Sopenharmony_ci} 648cb93a386Sopenharmony_ci 649cb93a386Sopenharmony_cibool DawnTestEnvironment::RunSuppressedTests() const { 650cb93a386Sopenharmony_ci return mRunSuppressedTests; 651cb93a386Sopenharmony_ci} 652cb93a386Sopenharmony_ci 653cb93a386Sopenharmony_cidawn_native::BackendValidationLevel DawnTestEnvironment::GetBackendValidationLevel() const { 654cb93a386Sopenharmony_ci return mBackendValidationLevel; 655cb93a386Sopenharmony_ci} 656cb93a386Sopenharmony_ci 657cb93a386Sopenharmony_cidawn_native::Instance* DawnTestEnvironment::GetInstance() const { 658cb93a386Sopenharmony_ci return mInstance.get(); 659cb93a386Sopenharmony_ci} 660cb93a386Sopenharmony_ci 661cb93a386Sopenharmony_cibool DawnTestEnvironment::HasVendorIdFilter() const { 662cb93a386Sopenharmony_ci return mHasVendorIdFilter; 663cb93a386Sopenharmony_ci} 664cb93a386Sopenharmony_ci 665cb93a386Sopenharmony_ciuint32_t DawnTestEnvironment::GetVendorIdFilter() const { 666cb93a386Sopenharmony_ci return mVendorIdFilter; 667cb93a386Sopenharmony_ci} 668cb93a386Sopenharmony_ci 669cb93a386Sopenharmony_cibool DawnTestEnvironment::HasBackendTypeFilter() const { 670cb93a386Sopenharmony_ci return mHasBackendTypeFilter; 671cb93a386Sopenharmony_ci} 672cb93a386Sopenharmony_ci 673cb93a386Sopenharmony_ciwgpu::BackendType DawnTestEnvironment::GetBackendTypeFilter() const { 674cb93a386Sopenharmony_ci return mBackendTypeFilter; 675cb93a386Sopenharmony_ci} 676cb93a386Sopenharmony_ci 677cb93a386Sopenharmony_ciconst char* DawnTestEnvironment::GetWireTraceDir() const { 678cb93a386Sopenharmony_ci if (mWireTraceDir.length() == 0) { 679cb93a386Sopenharmony_ci return nullptr; 680cb93a386Sopenharmony_ci } 681cb93a386Sopenharmony_ci return mWireTraceDir.c_str(); 682cb93a386Sopenharmony_ci} 683cb93a386Sopenharmony_ci 684cb93a386Sopenharmony_ciconst std::vector<std::string>& DawnTestEnvironment::GetEnabledToggles() const { 685cb93a386Sopenharmony_ci return mToggleParser.GetEnabledToggles(); 686cb93a386Sopenharmony_ci} 687cb93a386Sopenharmony_ci 688cb93a386Sopenharmony_ciconst std::vector<std::string>& DawnTestEnvironment::GetDisabledToggles() const { 689cb93a386Sopenharmony_ci return mToggleParser.GetDisabledToggles(); 690cb93a386Sopenharmony_ci} 691cb93a386Sopenharmony_ci 692cb93a386Sopenharmony_ci// Implementation of DawnTest 693cb93a386Sopenharmony_ci 694cb93a386Sopenharmony_ciDawnTestBase::DawnTestBase(const AdapterTestParam& param) 695cb93a386Sopenharmony_ci : mParam(param), 696cb93a386Sopenharmony_ci mWireHelper(utils::CreateWireHelper(gTestEnv->UsesWire(), gTestEnv->GetWireTraceDir())) { 697cb93a386Sopenharmony_ci} 698cb93a386Sopenharmony_ci 699cb93a386Sopenharmony_ciDawnTestBase::~DawnTestBase() { 700cb93a386Sopenharmony_ci // We need to destroy child objects before the Device 701cb93a386Sopenharmony_ci mReadbackSlots.clear(); 702cb93a386Sopenharmony_ci queue = wgpu::Queue(); 703cb93a386Sopenharmony_ci device = wgpu::Device(); 704cb93a386Sopenharmony_ci 705cb93a386Sopenharmony_ci // D3D12's GPU-based validation will accumulate objects over time if the backend device is not 706cb93a386Sopenharmony_ci // destroyed and recreated, so we reset it here. 707cb93a386Sopenharmony_ci if (IsD3D12() && IsBackendValidationEnabled()) { 708cb93a386Sopenharmony_ci mBackendAdapter.ResetInternalDeviceForTesting(); 709cb93a386Sopenharmony_ci } 710cb93a386Sopenharmony_ci mWireHelper.reset(); 711cb93a386Sopenharmony_ci} 712cb93a386Sopenharmony_ci 713cb93a386Sopenharmony_cibool DawnTestBase::IsD3D12() const { 714cb93a386Sopenharmony_ci return mParam.adapterProperties.backendType == wgpu::BackendType::D3D12; 715cb93a386Sopenharmony_ci} 716cb93a386Sopenharmony_ci 717cb93a386Sopenharmony_cibool DawnTestBase::IsMetal() const { 718cb93a386Sopenharmony_ci return mParam.adapterProperties.backendType == wgpu::BackendType::Metal; 719cb93a386Sopenharmony_ci} 720cb93a386Sopenharmony_ci 721cb93a386Sopenharmony_cibool DawnTestBase::IsNull() const { 722cb93a386Sopenharmony_ci return mParam.adapterProperties.backendType == wgpu::BackendType::Null; 723cb93a386Sopenharmony_ci} 724cb93a386Sopenharmony_ci 725cb93a386Sopenharmony_cibool DawnTestBase::IsOpenGL() const { 726cb93a386Sopenharmony_ci return mParam.adapterProperties.backendType == wgpu::BackendType::OpenGL; 727cb93a386Sopenharmony_ci} 728cb93a386Sopenharmony_ci 729cb93a386Sopenharmony_cibool DawnTestBase::IsOpenGLES() const { 730cb93a386Sopenharmony_ci return mParam.adapterProperties.backendType == wgpu::BackendType::OpenGLES; 731cb93a386Sopenharmony_ci} 732cb93a386Sopenharmony_ci 733cb93a386Sopenharmony_cibool DawnTestBase::IsVulkan() const { 734cb93a386Sopenharmony_ci return mParam.adapterProperties.backendType == wgpu::BackendType::Vulkan; 735cb93a386Sopenharmony_ci} 736cb93a386Sopenharmony_ci 737cb93a386Sopenharmony_cibool DawnTestBase::IsAMD() const { 738cb93a386Sopenharmony_ci return gpu_info::IsAMD(mParam.adapterProperties.vendorID); 739cb93a386Sopenharmony_ci} 740cb93a386Sopenharmony_ci 741cb93a386Sopenharmony_cibool DawnTestBase::IsARM() const { 742cb93a386Sopenharmony_ci return gpu_info::IsARM(mParam.adapterProperties.vendorID); 743cb93a386Sopenharmony_ci} 744cb93a386Sopenharmony_ci 745cb93a386Sopenharmony_cibool DawnTestBase::IsImgTec() const { 746cb93a386Sopenharmony_ci return gpu_info::IsImgTec(mParam.adapterProperties.vendorID); 747cb93a386Sopenharmony_ci} 748cb93a386Sopenharmony_ci 749cb93a386Sopenharmony_cibool DawnTestBase::IsIntel() const { 750cb93a386Sopenharmony_ci return gpu_info::IsIntel(mParam.adapterProperties.vendorID); 751cb93a386Sopenharmony_ci} 752cb93a386Sopenharmony_ci 753cb93a386Sopenharmony_cibool DawnTestBase::IsNvidia() const { 754cb93a386Sopenharmony_ci return gpu_info::IsNvidia(mParam.adapterProperties.vendorID); 755cb93a386Sopenharmony_ci} 756cb93a386Sopenharmony_ci 757cb93a386Sopenharmony_cibool DawnTestBase::IsQualcomm() const { 758cb93a386Sopenharmony_ci return gpu_info::IsQualcomm(mParam.adapterProperties.vendorID); 759cb93a386Sopenharmony_ci} 760cb93a386Sopenharmony_ci 761cb93a386Sopenharmony_cibool DawnTestBase::IsSwiftshader() const { 762cb93a386Sopenharmony_ci return gpu_info::IsSwiftshader(mParam.adapterProperties.vendorID, 763cb93a386Sopenharmony_ci mParam.adapterProperties.deviceID); 764cb93a386Sopenharmony_ci} 765cb93a386Sopenharmony_ci 766cb93a386Sopenharmony_cibool DawnTestBase::IsANGLE() const { 767cb93a386Sopenharmony_ci return !mParam.adapterProperties.adapterName.find("ANGLE"); 768cb93a386Sopenharmony_ci} 769cb93a386Sopenharmony_ci 770cb93a386Sopenharmony_cibool DawnTestBase::IsWARP() const { 771cb93a386Sopenharmony_ci return gpu_info::IsWARP(mParam.adapterProperties.vendorID, mParam.adapterProperties.deviceID); 772cb93a386Sopenharmony_ci} 773cb93a386Sopenharmony_ci 774cb93a386Sopenharmony_cibool DawnTestBase::IsWindows() const { 775cb93a386Sopenharmony_ci#ifdef DAWN_PLATFORM_WINDOWS 776cb93a386Sopenharmony_ci return true; 777cb93a386Sopenharmony_ci#else 778cb93a386Sopenharmony_ci return false; 779cb93a386Sopenharmony_ci#endif 780cb93a386Sopenharmony_ci} 781cb93a386Sopenharmony_ci 782cb93a386Sopenharmony_cibool DawnTestBase::IsLinux() const { 783cb93a386Sopenharmony_ci#ifdef DAWN_PLATFORM_LINUX 784cb93a386Sopenharmony_ci return true; 785cb93a386Sopenharmony_ci#else 786cb93a386Sopenharmony_ci return false; 787cb93a386Sopenharmony_ci#endif 788cb93a386Sopenharmony_ci} 789cb93a386Sopenharmony_ci 790cb93a386Sopenharmony_cibool DawnTestBase::IsMacOS(int32_t majorVersion, int32_t minorVersion) const { 791cb93a386Sopenharmony_ci#ifdef DAWN_PLATFORM_MACOS 792cb93a386Sopenharmony_ci if (majorVersion == -1 && minorVersion == -1) { 793cb93a386Sopenharmony_ci return true; 794cb93a386Sopenharmony_ci } 795cb93a386Sopenharmony_ci int32_t majorVersionOut, minorVersionOut = 0; 796cb93a386Sopenharmony_ci GetMacOSVersion(&majorVersionOut, &minorVersionOut); 797cb93a386Sopenharmony_ci return (majorVersion != -1 && majorVersion == majorVersionOut) && 798cb93a386Sopenharmony_ci (minorVersion != -1 && minorVersion == minorVersionOut); 799cb93a386Sopenharmony_ci#else 800cb93a386Sopenharmony_ci return false; 801cb93a386Sopenharmony_ci#endif 802cb93a386Sopenharmony_ci} 803cb93a386Sopenharmony_ci 804cb93a386Sopenharmony_cibool DawnTestBase::UsesWire() const { 805cb93a386Sopenharmony_ci return gTestEnv->UsesWire(); 806cb93a386Sopenharmony_ci} 807cb93a386Sopenharmony_ci 808cb93a386Sopenharmony_cibool DawnTestBase::IsBackendValidationEnabled() const { 809cb93a386Sopenharmony_ci return gTestEnv->GetBackendValidationLevel() != dawn_native::BackendValidationLevel::Disabled; 810cb93a386Sopenharmony_ci} 811cb93a386Sopenharmony_ci 812cb93a386Sopenharmony_cibool DawnTestBase::RunSuppressedTests() const { 813cb93a386Sopenharmony_ci return gTestEnv->RunSuppressedTests(); 814cb93a386Sopenharmony_ci} 815cb93a386Sopenharmony_ci 816cb93a386Sopenharmony_cibool DawnTestBase::IsDXC() const { 817cb93a386Sopenharmony_ci return HasToggleEnabled("use_dxc"); 818cb93a386Sopenharmony_ci} 819cb93a386Sopenharmony_ci 820cb93a386Sopenharmony_cibool DawnTestBase::IsAsan() const { 821cb93a386Sopenharmony_ci#if defined(ADDRESS_SANITIZER) 822cb93a386Sopenharmony_ci return true; 823cb93a386Sopenharmony_ci#else 824cb93a386Sopenharmony_ci return false; 825cb93a386Sopenharmony_ci#endif 826cb93a386Sopenharmony_ci} 827cb93a386Sopenharmony_ci 828cb93a386Sopenharmony_cibool DawnTestBase::HasToggleEnabled(const char* toggle) const { 829cb93a386Sopenharmony_ci auto toggles = dawn_native::GetTogglesUsed(backendDevice); 830cb93a386Sopenharmony_ci return std::find_if(toggles.begin(), toggles.end(), [toggle](const char* name) { 831cb93a386Sopenharmony_ci return strcmp(toggle, name) == 0; 832cb93a386Sopenharmony_ci }) != toggles.end(); 833cb93a386Sopenharmony_ci} 834cb93a386Sopenharmony_ci 835cb93a386Sopenharmony_cibool DawnTestBase::HasVendorIdFilter() const { 836cb93a386Sopenharmony_ci return gTestEnv->HasVendorIdFilter(); 837cb93a386Sopenharmony_ci} 838cb93a386Sopenharmony_ci 839cb93a386Sopenharmony_ciuint32_t DawnTestBase::GetVendorIdFilter() const { 840cb93a386Sopenharmony_ci return gTestEnv->GetVendorIdFilter(); 841cb93a386Sopenharmony_ci} 842cb93a386Sopenharmony_ci 843cb93a386Sopenharmony_cibool DawnTestBase::HasBackendTypeFilter() const { 844cb93a386Sopenharmony_ci return gTestEnv->HasBackendTypeFilter(); 845cb93a386Sopenharmony_ci} 846cb93a386Sopenharmony_ci 847cb93a386Sopenharmony_ciwgpu::BackendType DawnTestBase::GetBackendTypeFilter() const { 848cb93a386Sopenharmony_ci return gTestEnv->GetBackendTypeFilter(); 849cb93a386Sopenharmony_ci} 850cb93a386Sopenharmony_ci 851cb93a386Sopenharmony_ciwgpu::Instance DawnTestBase::GetInstance() const { 852cb93a386Sopenharmony_ci return gTestEnv->GetInstance()->Get(); 853cb93a386Sopenharmony_ci} 854cb93a386Sopenharmony_ci 855cb93a386Sopenharmony_cidawn_native::Adapter DawnTestBase::GetAdapter() const { 856cb93a386Sopenharmony_ci return mBackendAdapter; 857cb93a386Sopenharmony_ci} 858cb93a386Sopenharmony_ci 859cb93a386Sopenharmony_cistd::vector<const char*> DawnTestBase::GetRequiredFeatures() { 860cb93a386Sopenharmony_ci return {}; 861cb93a386Sopenharmony_ci} 862cb93a386Sopenharmony_ci 863cb93a386Sopenharmony_ciwgpu::RequiredLimits DawnTestBase::GetRequiredLimits(const wgpu::SupportedLimits&) { 864cb93a386Sopenharmony_ci return {}; 865cb93a386Sopenharmony_ci} 866cb93a386Sopenharmony_ci 867cb93a386Sopenharmony_ciconst wgpu::AdapterProperties& DawnTestBase::GetAdapterProperties() const { 868cb93a386Sopenharmony_ci return mParam.adapterProperties; 869cb93a386Sopenharmony_ci} 870cb93a386Sopenharmony_ci 871cb93a386Sopenharmony_ciwgpu::SupportedLimits DawnTestBase::GetSupportedLimits() { 872cb93a386Sopenharmony_ci WGPUSupportedLimits supportedLimits; 873cb93a386Sopenharmony_ci supportedLimits.nextInChain = nullptr; 874cb93a386Sopenharmony_ci dawn_native::GetProcs().deviceGetLimits(backendDevice, &supportedLimits); 875cb93a386Sopenharmony_ci return *reinterpret_cast<wgpu::SupportedLimits*>(&supportedLimits); 876cb93a386Sopenharmony_ci} 877cb93a386Sopenharmony_ci 878cb93a386Sopenharmony_cibool DawnTestBase::SupportsFeatures(const std::vector<const char*>& features) { 879cb93a386Sopenharmony_ci ASSERT(mBackendAdapter); 880cb93a386Sopenharmony_ci std::set<std::string> supportedFeaturesSet; 881cb93a386Sopenharmony_ci for (const char* supportedFeatureName : mBackendAdapter.GetSupportedFeatures()) { 882cb93a386Sopenharmony_ci supportedFeaturesSet.insert(supportedFeatureName); 883cb93a386Sopenharmony_ci } 884cb93a386Sopenharmony_ci 885cb93a386Sopenharmony_ci for (const char* featureName : features) { 886cb93a386Sopenharmony_ci if (supportedFeaturesSet.find(featureName) == supportedFeaturesSet.end()) { 887cb93a386Sopenharmony_ci return false; 888cb93a386Sopenharmony_ci } 889cb93a386Sopenharmony_ci } 890cb93a386Sopenharmony_ci 891cb93a386Sopenharmony_ci return true; 892cb93a386Sopenharmony_ci} 893cb93a386Sopenharmony_ci 894cb93a386Sopenharmony_civoid DawnTestBase::SetUp() { 895cb93a386Sopenharmony_ci { 896cb93a386Sopenharmony_ci // Find the adapter that exactly matches our adapter properties. 897cb93a386Sopenharmony_ci const auto& adapters = gTestEnv->GetInstance()->GetAdapters(); 898cb93a386Sopenharmony_ci const auto& it = std::find_if( 899cb93a386Sopenharmony_ci adapters.begin(), adapters.end(), [&](const dawn_native::Adapter& adapter) { 900cb93a386Sopenharmony_ci wgpu::AdapterProperties properties; 901cb93a386Sopenharmony_ci adapter.GetProperties(&properties); 902cb93a386Sopenharmony_ci 903cb93a386Sopenharmony_ci return (mParam.adapterProperties.selected && 904cb93a386Sopenharmony_ci properties.deviceID == mParam.adapterProperties.deviceID && 905cb93a386Sopenharmony_ci properties.vendorID == mParam.adapterProperties.vendorID && 906cb93a386Sopenharmony_ci properties.adapterType == mParam.adapterProperties.adapterType && 907cb93a386Sopenharmony_ci properties.backendType == mParam.adapterProperties.backendType && 908cb93a386Sopenharmony_ci strcmp(properties.name, mParam.adapterProperties.adapterName.c_str()) == 0); 909cb93a386Sopenharmony_ci }); 910cb93a386Sopenharmony_ci ASSERT(it != adapters.end()); 911cb93a386Sopenharmony_ci mBackendAdapter = *it; 912cb93a386Sopenharmony_ci } 913cb93a386Sopenharmony_ci 914cb93a386Sopenharmony_ci // Setup the per-test platform. Tests can provide one by overloading CreateTestPlatform. 915cb93a386Sopenharmony_ci mTestPlatform = CreateTestPlatform(); 916cb93a386Sopenharmony_ci gTestEnv->GetInstance()->SetPlatform(mTestPlatform.get()); 917cb93a386Sopenharmony_ci 918cb93a386Sopenharmony_ci // Create the device from the adapter 919cb93a386Sopenharmony_ci for (const char* forceEnabledWorkaround : mParam.forceEnabledWorkarounds) { 920cb93a386Sopenharmony_ci ASSERT(gTestEnv->GetInstance()->GetToggleInfo(forceEnabledWorkaround) != nullptr); 921cb93a386Sopenharmony_ci } 922cb93a386Sopenharmony_ci for (const char* forceDisabledWorkaround : mParam.forceDisabledWorkarounds) { 923cb93a386Sopenharmony_ci ASSERT(gTestEnv->GetInstance()->GetToggleInfo(forceDisabledWorkaround) != nullptr); 924cb93a386Sopenharmony_ci } 925cb93a386Sopenharmony_ci dawn_native::DawnDeviceDescriptor deviceDescriptor = {}; 926cb93a386Sopenharmony_ci deviceDescriptor.forceEnabledToggles = mParam.forceEnabledWorkarounds; 927cb93a386Sopenharmony_ci deviceDescriptor.forceDisabledToggles = mParam.forceDisabledWorkarounds; 928cb93a386Sopenharmony_ci deviceDescriptor.requiredFeatures = GetRequiredFeatures(); 929cb93a386Sopenharmony_ci 930cb93a386Sopenharmony_ci wgpu::SupportedLimits supportedLimits; 931cb93a386Sopenharmony_ci mBackendAdapter.GetLimits(reinterpret_cast<WGPUSupportedLimits*>(&supportedLimits)); 932cb93a386Sopenharmony_ci wgpu::RequiredLimits requiredLimits = GetRequiredLimits(supportedLimits); 933cb93a386Sopenharmony_ci deviceDescriptor.requiredLimits = reinterpret_cast<WGPURequiredLimits*>(&requiredLimits); 934cb93a386Sopenharmony_ci 935cb93a386Sopenharmony_ci // Disabled disallowing unsafe APIs so we can test them. 936cb93a386Sopenharmony_ci deviceDescriptor.forceDisabledToggles.push_back("disallow_unsafe_apis"); 937cb93a386Sopenharmony_ci 938cb93a386Sopenharmony_ci for (const std::string& toggle : gTestEnv->GetEnabledToggles()) { 939cb93a386Sopenharmony_ci const dawn_native::ToggleInfo* info = 940cb93a386Sopenharmony_ci gTestEnv->GetInstance()->GetToggleInfo(toggle.c_str()); 941cb93a386Sopenharmony_ci ASSERT(info != nullptr); 942cb93a386Sopenharmony_ci deviceDescriptor.forceEnabledToggles.push_back(info->name); 943cb93a386Sopenharmony_ci } 944cb93a386Sopenharmony_ci 945cb93a386Sopenharmony_ci for (const std::string& toggle : gTestEnv->GetDisabledToggles()) { 946cb93a386Sopenharmony_ci const dawn_native::ToggleInfo* info = 947cb93a386Sopenharmony_ci gTestEnv->GetInstance()->GetToggleInfo(toggle.c_str()); 948cb93a386Sopenharmony_ci ASSERT(info != nullptr); 949cb93a386Sopenharmony_ci deviceDescriptor.forceDisabledToggles.push_back(info->name); 950cb93a386Sopenharmony_ci } 951cb93a386Sopenharmony_ci 952cb93a386Sopenharmony_ci std::tie(device, backendDevice) = 953cb93a386Sopenharmony_ci mWireHelper->RegisterDevice(mBackendAdapter.CreateDevice(&deviceDescriptor)); 954cb93a386Sopenharmony_ci ASSERT_NE(nullptr, backendDevice); 955cb93a386Sopenharmony_ci 956cb93a386Sopenharmony_ci std::string traceName = 957cb93a386Sopenharmony_ci std::string(::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name()) + 958cb93a386Sopenharmony_ci "_" + ::testing::UnitTest::GetInstance()->current_test_info()->name(); 959cb93a386Sopenharmony_ci mWireHelper->BeginWireTrace(traceName.c_str()); 960cb93a386Sopenharmony_ci 961cb93a386Sopenharmony_ci queue = device.GetQueue(); 962cb93a386Sopenharmony_ci 963cb93a386Sopenharmony_ci device.SetUncapturedErrorCallback(OnDeviceError, this); 964cb93a386Sopenharmony_ci device.SetDeviceLostCallback(OnDeviceLost, this); 965cb93a386Sopenharmony_ci#if defined(DAWN_ENABLE_BACKEND_DESKTOP_GL) 966cb93a386Sopenharmony_ci if (IsOpenGL()) { 967cb93a386Sopenharmony_ci glfwMakeContextCurrent(gTestEnv->GetOpenGLWindow()); 968cb93a386Sopenharmony_ci } 969cb93a386Sopenharmony_ci#endif // defined(DAWN_ENABLE_BACKEND_DESKTOP_GL) 970cb93a386Sopenharmony_ci#if defined(DAWN_ENABLE_BACKEND_OPENGLES) 971cb93a386Sopenharmony_ci if (IsOpenGLES()) { 972cb93a386Sopenharmony_ci glfwMakeContextCurrent(gTestEnv->GetOpenGLESWindow()); 973cb93a386Sopenharmony_ci } 974cb93a386Sopenharmony_ci#endif // defined(DAWN_ENABLE_BACKEND_OPENGLES) 975cb93a386Sopenharmony_ci 976cb93a386Sopenharmony_ci device.SetLoggingCallback( 977cb93a386Sopenharmony_ci [](WGPULoggingType type, char const* message, void*) { 978cb93a386Sopenharmony_ci switch (type) { 979cb93a386Sopenharmony_ci case WGPULoggingType_Verbose: 980cb93a386Sopenharmony_ci dawn::DebugLog() << message; 981cb93a386Sopenharmony_ci break; 982cb93a386Sopenharmony_ci case WGPULoggingType_Warning: 983cb93a386Sopenharmony_ci dawn::WarningLog() << message; 984cb93a386Sopenharmony_ci break; 985cb93a386Sopenharmony_ci case WGPULoggingType_Error: 986cb93a386Sopenharmony_ci dawn::ErrorLog() << message; 987cb93a386Sopenharmony_ci break; 988cb93a386Sopenharmony_ci default: 989cb93a386Sopenharmony_ci dawn::InfoLog() << message; 990cb93a386Sopenharmony_ci break; 991cb93a386Sopenharmony_ci } 992cb93a386Sopenharmony_ci }, 993cb93a386Sopenharmony_ci nullptr); 994cb93a386Sopenharmony_ci} 995cb93a386Sopenharmony_ci 996cb93a386Sopenharmony_civoid DawnTestBase::TearDown() { 997cb93a386Sopenharmony_ci FlushWire(); 998cb93a386Sopenharmony_ci 999cb93a386Sopenharmony_ci MapSlotsSynchronously(); 1000cb93a386Sopenharmony_ci ResolveExpectations(); 1001cb93a386Sopenharmony_ci 1002cb93a386Sopenharmony_ci for (size_t i = 0; i < mReadbackSlots.size(); ++i) { 1003cb93a386Sopenharmony_ci mReadbackSlots[i].buffer.Unmap(); 1004cb93a386Sopenharmony_ci } 1005cb93a386Sopenharmony_ci 1006cb93a386Sopenharmony_ci if (!UsesWire()) { 1007cb93a386Sopenharmony_ci EXPECT_EQ(mLastWarningCount, 1008cb93a386Sopenharmony_ci dawn_native::GetDeprecationWarningCountForTesting(device.Get())); 1009cb93a386Sopenharmony_ci } 1010cb93a386Sopenharmony_ci 1011cb93a386Sopenharmony_ci // The device will be destroyed soon after, so we want to set the expectation. 1012cb93a386Sopenharmony_ci ExpectDeviceDestruction(); 1013cb93a386Sopenharmony_ci} 1014cb93a386Sopenharmony_ci 1015cb93a386Sopenharmony_civoid DawnTestBase::StartExpectDeviceError(testing::Matcher<std::string> errorMatcher) { 1016cb93a386Sopenharmony_ci mExpectError = true; 1017cb93a386Sopenharmony_ci mError = false; 1018cb93a386Sopenharmony_ci mErrorMatcher = errorMatcher; 1019cb93a386Sopenharmony_ci} 1020cb93a386Sopenharmony_ci 1021cb93a386Sopenharmony_cibool DawnTestBase::EndExpectDeviceError() { 1022cb93a386Sopenharmony_ci mExpectError = false; 1023cb93a386Sopenharmony_ci mErrorMatcher = testing::_; 1024cb93a386Sopenharmony_ci return mError; 1025cb93a386Sopenharmony_ci} 1026cb93a386Sopenharmony_ci 1027cb93a386Sopenharmony_civoid DawnTestBase::ExpectDeviceDestruction() { 1028cb93a386Sopenharmony_ci mExpectDestruction = true; 1029cb93a386Sopenharmony_ci} 1030cb93a386Sopenharmony_ci 1031cb93a386Sopenharmony_ci// static 1032cb93a386Sopenharmony_civoid DawnTestBase::OnDeviceError(WGPUErrorType type, const char* message, void* userdata) { 1033cb93a386Sopenharmony_ci ASSERT(type != WGPUErrorType_NoError); 1034cb93a386Sopenharmony_ci DawnTestBase* self = static_cast<DawnTestBase*>(userdata); 1035cb93a386Sopenharmony_ci 1036cb93a386Sopenharmony_ci ASSERT_TRUE(self->mExpectError) << "Got unexpected device error: " << message; 1037cb93a386Sopenharmony_ci ASSERT_FALSE(self->mError) << "Got two errors in expect block"; 1038cb93a386Sopenharmony_ci if (self->mExpectError) { 1039cb93a386Sopenharmony_ci ASSERT_THAT(message, self->mErrorMatcher); 1040cb93a386Sopenharmony_ci } 1041cb93a386Sopenharmony_ci self->mError = true; 1042cb93a386Sopenharmony_ci} 1043cb93a386Sopenharmony_ci 1044cb93a386Sopenharmony_civoid DawnTestBase::OnDeviceLost(WGPUDeviceLostReason reason, const char* message, void* userdata) { 1045cb93a386Sopenharmony_ci DawnTestBase* self = static_cast<DawnTestBase*>(userdata); 1046cb93a386Sopenharmony_ci if (self->mExpectDestruction) { 1047cb93a386Sopenharmony_ci EXPECT_EQ(reason, WGPUDeviceLostReason_Destroyed); 1048cb93a386Sopenharmony_ci return; 1049cb93a386Sopenharmony_ci } 1050cb93a386Sopenharmony_ci // Using ADD_FAILURE + ASSERT instead of FAIL to prevent the current test from continuing with a 1051cb93a386Sopenharmony_ci // corrupt state. 1052cb93a386Sopenharmony_ci ADD_FAILURE() << "Device lost during test: " << message; 1053cb93a386Sopenharmony_ci ASSERT(false); 1054cb93a386Sopenharmony_ci} 1055cb93a386Sopenharmony_ci 1056cb93a386Sopenharmony_cistd::ostringstream& DawnTestBase::AddBufferExpectation(const char* file, 1057cb93a386Sopenharmony_ci int line, 1058cb93a386Sopenharmony_ci const wgpu::Buffer& buffer, 1059cb93a386Sopenharmony_ci uint64_t offset, 1060cb93a386Sopenharmony_ci uint64_t size, 1061cb93a386Sopenharmony_ci detail::Expectation* expectation) { 1062cb93a386Sopenharmony_ci auto readback = ReserveReadback(size); 1063cb93a386Sopenharmony_ci 1064cb93a386Sopenharmony_ci // We need to enqueue the copy immediately because by the time we resolve the expectation, 1065cb93a386Sopenharmony_ci // the buffer might have been modified. 1066cb93a386Sopenharmony_ci wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); 1067cb93a386Sopenharmony_ci encoder.CopyBufferToBuffer(buffer, offset, readback.buffer, readback.offset, size); 1068cb93a386Sopenharmony_ci 1069cb93a386Sopenharmony_ci wgpu::CommandBuffer commands = encoder.Finish(); 1070cb93a386Sopenharmony_ci queue.Submit(1, &commands); 1071cb93a386Sopenharmony_ci 1072cb93a386Sopenharmony_ci DeferredExpectation deferred; 1073cb93a386Sopenharmony_ci deferred.file = file; 1074cb93a386Sopenharmony_ci deferred.line = line; 1075cb93a386Sopenharmony_ci deferred.readbackSlot = readback.slot; 1076cb93a386Sopenharmony_ci deferred.readbackOffset = readback.offset; 1077cb93a386Sopenharmony_ci deferred.size = size; 1078cb93a386Sopenharmony_ci deferred.rowBytes = size; 1079cb93a386Sopenharmony_ci deferred.bytesPerRow = size; 1080cb93a386Sopenharmony_ci deferred.expectation.reset(expectation); 1081cb93a386Sopenharmony_ci 1082cb93a386Sopenharmony_ci mDeferredExpectations.push_back(std::move(deferred)); 1083cb93a386Sopenharmony_ci mDeferredExpectations.back().message = std::make_unique<std::ostringstream>(); 1084cb93a386Sopenharmony_ci return *(mDeferredExpectations.back().message.get()); 1085cb93a386Sopenharmony_ci} 1086cb93a386Sopenharmony_ci 1087cb93a386Sopenharmony_cistd::ostringstream& DawnTestBase::AddTextureExpectationImpl(const char* file, 1088cb93a386Sopenharmony_ci int line, 1089cb93a386Sopenharmony_ci detail::Expectation* expectation, 1090cb93a386Sopenharmony_ci const wgpu::Texture& texture, 1091cb93a386Sopenharmony_ci wgpu::Origin3D origin, 1092cb93a386Sopenharmony_ci wgpu::Extent3D extent, 1093cb93a386Sopenharmony_ci uint32_t level, 1094cb93a386Sopenharmony_ci wgpu::TextureAspect aspect, 1095cb93a386Sopenharmony_ci uint32_t dataSize, 1096cb93a386Sopenharmony_ci uint32_t bytesPerRow) { 1097cb93a386Sopenharmony_ci if (bytesPerRow == 0) { 1098cb93a386Sopenharmony_ci bytesPerRow = Align(extent.width * dataSize, kTextureBytesPerRowAlignment); 1099cb93a386Sopenharmony_ci } else { 1100cb93a386Sopenharmony_ci ASSERT(bytesPerRow >= extent.width * dataSize); 1101cb93a386Sopenharmony_ci ASSERT(bytesPerRow == Align(bytesPerRow, kTextureBytesPerRowAlignment)); 1102cb93a386Sopenharmony_ci } 1103cb93a386Sopenharmony_ci 1104cb93a386Sopenharmony_ci uint32_t rowsPerImage = extent.height; 1105cb93a386Sopenharmony_ci uint32_t size = utils::RequiredBytesInCopy(bytesPerRow, rowsPerImage, extent.width, 1106cb93a386Sopenharmony_ci extent.height, extent.depthOrArrayLayers, dataSize); 1107cb93a386Sopenharmony_ci 1108cb93a386Sopenharmony_ci auto readback = ReserveReadback(Align(size, 4)); 1109cb93a386Sopenharmony_ci 1110cb93a386Sopenharmony_ci // We need to enqueue the copy immediately because by the time we resolve the expectation, 1111cb93a386Sopenharmony_ci // the texture might have been modified. 1112cb93a386Sopenharmony_ci wgpu::ImageCopyTexture imageCopyTexture = 1113cb93a386Sopenharmony_ci utils::CreateImageCopyTexture(texture, level, origin, aspect); 1114cb93a386Sopenharmony_ci wgpu::ImageCopyBuffer imageCopyBuffer = 1115cb93a386Sopenharmony_ci utils::CreateImageCopyBuffer(readback.buffer, readback.offset, bytesPerRow, rowsPerImage); 1116cb93a386Sopenharmony_ci 1117cb93a386Sopenharmony_ci wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); 1118cb93a386Sopenharmony_ci encoder.CopyTextureToBuffer(&imageCopyTexture, &imageCopyBuffer, &extent); 1119cb93a386Sopenharmony_ci 1120cb93a386Sopenharmony_ci wgpu::CommandBuffer commands = encoder.Finish(); 1121cb93a386Sopenharmony_ci queue.Submit(1, &commands); 1122cb93a386Sopenharmony_ci 1123cb93a386Sopenharmony_ci DeferredExpectation deferred; 1124cb93a386Sopenharmony_ci deferred.file = file; 1125cb93a386Sopenharmony_ci deferred.line = line; 1126cb93a386Sopenharmony_ci deferred.readbackSlot = readback.slot; 1127cb93a386Sopenharmony_ci deferred.readbackOffset = readback.offset; 1128cb93a386Sopenharmony_ci deferred.size = size; 1129cb93a386Sopenharmony_ci deferred.rowBytes = extent.width * dataSize; 1130cb93a386Sopenharmony_ci deferred.bytesPerRow = bytesPerRow; 1131cb93a386Sopenharmony_ci deferred.expectation.reset(expectation); 1132cb93a386Sopenharmony_ci 1133cb93a386Sopenharmony_ci mDeferredExpectations.push_back(std::move(deferred)); 1134cb93a386Sopenharmony_ci mDeferredExpectations.back().message = std::make_unique<std::ostringstream>(); 1135cb93a386Sopenharmony_ci return *(mDeferredExpectations.back().message.get()); 1136cb93a386Sopenharmony_ci} 1137cb93a386Sopenharmony_ci 1138cb93a386Sopenharmony_cistd::ostringstream& DawnTestBase::ExpectSampledFloatDataImpl(wgpu::TextureView textureView, 1139cb93a386Sopenharmony_ci const char* wgslTextureType, 1140cb93a386Sopenharmony_ci uint32_t width, 1141cb93a386Sopenharmony_ci uint32_t height, 1142cb93a386Sopenharmony_ci uint32_t componentCount, 1143cb93a386Sopenharmony_ci uint32_t sampleCount, 1144cb93a386Sopenharmony_ci detail::Expectation* expectation) { 1145cb93a386Sopenharmony_ci std::ostringstream shaderSource; 1146cb93a386Sopenharmony_ci shaderSource << "let width : u32 = " << width << "u;\n"; 1147cb93a386Sopenharmony_ci shaderSource << "[[group(0), binding(0)]] var tex : " << wgslTextureType << ";\n"; 1148cb93a386Sopenharmony_ci shaderSource << R"( 1149cb93a386Sopenharmony_ci [[block]] struct Result { 1150cb93a386Sopenharmony_ci values : array<f32>; 1151cb93a386Sopenharmony_ci }; 1152cb93a386Sopenharmony_ci [[group(0), binding(1)]] var<storage, read_write> result : Result; 1153cb93a386Sopenharmony_ci )"; 1154cb93a386Sopenharmony_ci shaderSource << "let componentCount : u32 = " << componentCount << "u;\n"; 1155cb93a386Sopenharmony_ci shaderSource << "let sampleCount : u32 = " << sampleCount << "u;\n"; 1156cb93a386Sopenharmony_ci 1157cb93a386Sopenharmony_ci shaderSource << "fn doTextureLoad(t: " << wgslTextureType 1158cb93a386Sopenharmony_ci << ", coord: vec2<i32>, sample: u32, component: u32) -> f32"; 1159cb93a386Sopenharmony_ci if (sampleCount > 1) { 1160cb93a386Sopenharmony_ci shaderSource << R"({ 1161cb93a386Sopenharmony_ci return textureLoad(tex, coord, i32(sample))[component]; 1162cb93a386Sopenharmony_ci })"; 1163cb93a386Sopenharmony_ci } else { 1164cb93a386Sopenharmony_ci if (strcmp(wgslTextureType, "texture_depth_2d") == 0) { 1165cb93a386Sopenharmony_ci ASSERT(componentCount == 1); 1166cb93a386Sopenharmony_ci shaderSource << R"({ 1167cb93a386Sopenharmony_ci return textureLoad(tex, coord, 0); 1168cb93a386Sopenharmony_ci })"; 1169cb93a386Sopenharmony_ci } else { 1170cb93a386Sopenharmony_ci shaderSource << R"({ 1171cb93a386Sopenharmony_ci return textureLoad(tex, coord, 0)[component]; 1172cb93a386Sopenharmony_ci })"; 1173cb93a386Sopenharmony_ci } 1174cb93a386Sopenharmony_ci } 1175cb93a386Sopenharmony_ci shaderSource << R"( 1176cb93a386Sopenharmony_ci [[stage(compute), workgroup_size(1)]] fn main( 1177cb93a386Sopenharmony_ci [[builtin(global_invocation_id)]] GlobalInvocationId : vec3<u32> 1178cb93a386Sopenharmony_ci ) { 1179cb93a386Sopenharmony_ci let baseOutIndex = GlobalInvocationId.y * width + GlobalInvocationId.x; 1180cb93a386Sopenharmony_ci for (var s = 0u; s < sampleCount; s = s + 1u) { 1181cb93a386Sopenharmony_ci for (var c = 0u; c < componentCount; c = c + 1u) { 1182cb93a386Sopenharmony_ci result.values[ 1183cb93a386Sopenharmony_ci baseOutIndex * sampleCount * componentCount + 1184cb93a386Sopenharmony_ci s * componentCount + 1185cb93a386Sopenharmony_ci c 1186cb93a386Sopenharmony_ci ] = doTextureLoad(tex, vec2<i32>(GlobalInvocationId.xy), s, c); 1187cb93a386Sopenharmony_ci } 1188cb93a386Sopenharmony_ci } 1189cb93a386Sopenharmony_ci } 1190cb93a386Sopenharmony_ci )"; 1191cb93a386Sopenharmony_ci 1192cb93a386Sopenharmony_ci wgpu::ShaderModule csModule = utils::CreateShaderModule(device, shaderSource.str().c_str()); 1193cb93a386Sopenharmony_ci 1194cb93a386Sopenharmony_ci wgpu::ComputePipelineDescriptor pipelineDescriptor; 1195cb93a386Sopenharmony_ci pipelineDescriptor.compute.module = csModule; 1196cb93a386Sopenharmony_ci pipelineDescriptor.compute.entryPoint = "main"; 1197cb93a386Sopenharmony_ci 1198cb93a386Sopenharmony_ci wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&pipelineDescriptor); 1199cb93a386Sopenharmony_ci 1200cb93a386Sopenharmony_ci // Create and initialize the slot buffer so that it won't unexpectedly affect the count of 1201cb93a386Sopenharmony_ci // resources lazily cleared. 1202cb93a386Sopenharmony_ci const std::vector<float> initialBufferData(width * height * componentCount * sampleCount, 0.f); 1203cb93a386Sopenharmony_ci wgpu::Buffer readbackBuffer = utils::CreateBufferFromData( 1204cb93a386Sopenharmony_ci device, initialBufferData.data(), sizeof(float) * initialBufferData.size(), 1205cb93a386Sopenharmony_ci wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::Storage); 1206cb93a386Sopenharmony_ci 1207cb93a386Sopenharmony_ci wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0), 1208cb93a386Sopenharmony_ci {{0, textureView}, {1, readbackBuffer}}); 1209cb93a386Sopenharmony_ci 1210cb93a386Sopenharmony_ci wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder(); 1211cb93a386Sopenharmony_ci wgpu::ComputePassEncoder pass = commandEncoder.BeginComputePass(); 1212cb93a386Sopenharmony_ci pass.SetPipeline(pipeline); 1213cb93a386Sopenharmony_ci pass.SetBindGroup(0, bindGroup); 1214cb93a386Sopenharmony_ci pass.Dispatch(width, height); 1215cb93a386Sopenharmony_ci pass.EndPass(); 1216cb93a386Sopenharmony_ci wgpu::CommandBuffer commands = commandEncoder.Finish(); 1217cb93a386Sopenharmony_ci queue.Submit(1, &commands); 1218cb93a386Sopenharmony_ci 1219cb93a386Sopenharmony_ci return EXPECT_BUFFER(readbackBuffer, 0, initialBufferData.size() * sizeof(float), expectation); 1220cb93a386Sopenharmony_ci} 1221cb93a386Sopenharmony_ci 1222cb93a386Sopenharmony_cistd::ostringstream& DawnTestBase::ExpectSampledFloatData(wgpu::Texture texture, 1223cb93a386Sopenharmony_ci uint32_t width, 1224cb93a386Sopenharmony_ci uint32_t height, 1225cb93a386Sopenharmony_ci uint32_t componentCount, 1226cb93a386Sopenharmony_ci uint32_t arrayLayer, 1227cb93a386Sopenharmony_ci uint32_t mipLevel, 1228cb93a386Sopenharmony_ci detail::Expectation* expectation) { 1229cb93a386Sopenharmony_ci wgpu::TextureViewDescriptor viewDesc = {}; 1230cb93a386Sopenharmony_ci viewDesc.dimension = wgpu::TextureViewDimension::e2D; 1231cb93a386Sopenharmony_ci viewDesc.baseMipLevel = mipLevel; 1232cb93a386Sopenharmony_ci viewDesc.mipLevelCount = 1; 1233cb93a386Sopenharmony_ci viewDesc.baseArrayLayer = arrayLayer; 1234cb93a386Sopenharmony_ci viewDesc.arrayLayerCount = 1; 1235cb93a386Sopenharmony_ci 1236cb93a386Sopenharmony_ci return ExpectSampledFloatDataImpl(texture.CreateView(&viewDesc), "texture_2d<f32>", width, 1237cb93a386Sopenharmony_ci height, componentCount, 1, expectation); 1238cb93a386Sopenharmony_ci} 1239cb93a386Sopenharmony_ci 1240cb93a386Sopenharmony_cistd::ostringstream& DawnTestBase::ExpectMultisampledFloatData(wgpu::Texture texture, 1241cb93a386Sopenharmony_ci uint32_t width, 1242cb93a386Sopenharmony_ci uint32_t height, 1243cb93a386Sopenharmony_ci uint32_t componentCount, 1244cb93a386Sopenharmony_ci uint32_t sampleCount, 1245cb93a386Sopenharmony_ci uint32_t arrayLayer, 1246cb93a386Sopenharmony_ci uint32_t mipLevel, 1247cb93a386Sopenharmony_ci detail::Expectation* expectation) { 1248cb93a386Sopenharmony_ci wgpu::TextureViewDescriptor viewDesc = {}; 1249cb93a386Sopenharmony_ci viewDesc.dimension = wgpu::TextureViewDimension::e2D; 1250cb93a386Sopenharmony_ci viewDesc.baseMipLevel = mipLevel; 1251cb93a386Sopenharmony_ci viewDesc.mipLevelCount = 1; 1252cb93a386Sopenharmony_ci viewDesc.baseArrayLayer = arrayLayer; 1253cb93a386Sopenharmony_ci viewDesc.arrayLayerCount = 1; 1254cb93a386Sopenharmony_ci 1255cb93a386Sopenharmony_ci return ExpectSampledFloatDataImpl(texture.CreateView(&viewDesc), "texture_multisampled_2d<f32>", 1256cb93a386Sopenharmony_ci width, height, componentCount, sampleCount, expectation); 1257cb93a386Sopenharmony_ci} 1258cb93a386Sopenharmony_ci 1259cb93a386Sopenharmony_cistd::ostringstream& DawnTestBase::ExpectSampledDepthData(wgpu::Texture texture, 1260cb93a386Sopenharmony_ci uint32_t width, 1261cb93a386Sopenharmony_ci uint32_t height, 1262cb93a386Sopenharmony_ci uint32_t arrayLayer, 1263cb93a386Sopenharmony_ci uint32_t mipLevel, 1264cb93a386Sopenharmony_ci detail::Expectation* expectation) { 1265cb93a386Sopenharmony_ci wgpu::TextureViewDescriptor viewDesc = {}; 1266cb93a386Sopenharmony_ci viewDesc.aspect = wgpu::TextureAspect::DepthOnly; 1267cb93a386Sopenharmony_ci viewDesc.dimension = wgpu::TextureViewDimension::e2D; 1268cb93a386Sopenharmony_ci viewDesc.baseMipLevel = mipLevel; 1269cb93a386Sopenharmony_ci viewDesc.mipLevelCount = 1; 1270cb93a386Sopenharmony_ci viewDesc.baseArrayLayer = arrayLayer; 1271cb93a386Sopenharmony_ci viewDesc.arrayLayerCount = 1; 1272cb93a386Sopenharmony_ci 1273cb93a386Sopenharmony_ci return ExpectSampledFloatDataImpl(texture.CreateView(&viewDesc), "texture_depth_2d", width, 1274cb93a386Sopenharmony_ci height, 1, 1, expectation); 1275cb93a386Sopenharmony_ci} 1276cb93a386Sopenharmony_ci 1277cb93a386Sopenharmony_cistd::ostringstream& DawnTestBase::ExpectAttachmentDepthStencilTestData( 1278cb93a386Sopenharmony_ci wgpu::Texture texture, 1279cb93a386Sopenharmony_ci wgpu::TextureFormat format, 1280cb93a386Sopenharmony_ci uint32_t width, 1281cb93a386Sopenharmony_ci uint32_t height, 1282cb93a386Sopenharmony_ci uint32_t arrayLayer, 1283cb93a386Sopenharmony_ci uint32_t mipLevel, 1284cb93a386Sopenharmony_ci std::vector<float> expectedDepth, 1285cb93a386Sopenharmony_ci uint8_t* expectedStencil) { 1286cb93a386Sopenharmony_ci wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder(); 1287cb93a386Sopenharmony_ci 1288cb93a386Sopenharmony_ci // Make the color attachment that we'll use to read back. 1289cb93a386Sopenharmony_ci wgpu::TextureDescriptor colorTexDesc = {}; 1290cb93a386Sopenharmony_ci colorTexDesc.size = {width, height, 1}; 1291cb93a386Sopenharmony_ci colorTexDesc.format = wgpu::TextureFormat::R32Uint; 1292cb93a386Sopenharmony_ci colorTexDesc.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc; 1293cb93a386Sopenharmony_ci wgpu::Texture colorTexture = device.CreateTexture(&colorTexDesc); 1294cb93a386Sopenharmony_ci 1295cb93a386Sopenharmony_ci wgpu::Texture depthDataTexture = nullptr; 1296cb93a386Sopenharmony_ci if (expectedDepth.size() > 0) { 1297cb93a386Sopenharmony_ci // Make a sampleable texture to store the depth data. We'll sample this in the 1298cb93a386Sopenharmony_ci // shader to output depth. 1299cb93a386Sopenharmony_ci wgpu::TextureDescriptor depthDataDesc = {}; 1300cb93a386Sopenharmony_ci depthDataDesc.size = {width, height, 1}; 1301cb93a386Sopenharmony_ci depthDataDesc.format = wgpu::TextureFormat::R32Float; 1302cb93a386Sopenharmony_ci depthDataDesc.usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopyDst; 1303cb93a386Sopenharmony_ci depthDataTexture = device.CreateTexture(&depthDataDesc); 1304cb93a386Sopenharmony_ci 1305cb93a386Sopenharmony_ci // Upload the depth data. 1306cb93a386Sopenharmony_ci wgpu::ImageCopyTexture imageCopyTexture = 1307cb93a386Sopenharmony_ci utils::CreateImageCopyTexture(depthDataTexture, 0, {0, 0, 0}); 1308cb93a386Sopenharmony_ci wgpu::TextureDataLayout textureDataLayout = 1309cb93a386Sopenharmony_ci utils::CreateTextureDataLayout(0, sizeof(float) * width); 1310cb93a386Sopenharmony_ci wgpu::Extent3D copyExtent = {width, height, 1}; 1311cb93a386Sopenharmony_ci 1312cb93a386Sopenharmony_ci queue.WriteTexture(&imageCopyTexture, expectedDepth.data(), 1313cb93a386Sopenharmony_ci sizeof(float) * expectedDepth.size(), &textureDataLayout, ©Extent); 1314cb93a386Sopenharmony_ci } 1315cb93a386Sopenharmony_ci 1316cb93a386Sopenharmony_ci // Pipeline for a full screen quad. 1317cb93a386Sopenharmony_ci utils::ComboRenderPipelineDescriptor pipelineDescriptor; 1318cb93a386Sopenharmony_ci 1319cb93a386Sopenharmony_ci pipelineDescriptor.vertex.module = utils::CreateShaderModule(device, R"( 1320cb93a386Sopenharmony_ci [[stage(vertex)]] 1321cb93a386Sopenharmony_ci fn main([[builtin(vertex_index)]] VertexIndex : u32) -> [[builtin(position)]] vec4<f32> { 1322cb93a386Sopenharmony_ci var pos = array<vec2<f32>, 3>( 1323cb93a386Sopenharmony_ci vec2<f32>(-1.0, -1.0), 1324cb93a386Sopenharmony_ci vec2<f32>( 3.0, -1.0), 1325cb93a386Sopenharmony_ci vec2<f32>(-1.0, 3.0)); 1326cb93a386Sopenharmony_ci return vec4<f32>(pos[VertexIndex], 0.0, 1.0); 1327cb93a386Sopenharmony_ci })"); 1328cb93a386Sopenharmony_ci 1329cb93a386Sopenharmony_ci if (depthDataTexture) { 1330cb93a386Sopenharmony_ci // Sample the input texture and write out depth. |result| will only be set to 1 if we 1331cb93a386Sopenharmony_ci // pass the depth test. 1332cb93a386Sopenharmony_ci pipelineDescriptor.cFragment.module = utils::CreateShaderModule(device, R"( 1333cb93a386Sopenharmony_ci [[group(0), binding(0)]] var texture0 : texture_2d<f32>; 1334cb93a386Sopenharmony_ci 1335cb93a386Sopenharmony_ci struct FragmentOut { 1336cb93a386Sopenharmony_ci [[location(0)]] result : u32; 1337cb93a386Sopenharmony_ci [[builtin(frag_depth)]] fragDepth : f32; 1338cb93a386Sopenharmony_ci }; 1339cb93a386Sopenharmony_ci 1340cb93a386Sopenharmony_ci [[stage(fragment)]] 1341cb93a386Sopenharmony_ci fn main([[builtin(position)]] FragCoord : vec4<f32>) -> FragmentOut { 1342cb93a386Sopenharmony_ci var output : FragmentOut; 1343cb93a386Sopenharmony_ci output.result = 1u; 1344cb93a386Sopenharmony_ci output.fragDepth = textureLoad(texture0, vec2<i32>(FragCoord.xy), 0)[0]; 1345cb93a386Sopenharmony_ci return output; 1346cb93a386Sopenharmony_ci })"); 1347cb93a386Sopenharmony_ci } else { 1348cb93a386Sopenharmony_ci pipelineDescriptor.cFragment.module = utils::CreateShaderModule(device, R"( 1349cb93a386Sopenharmony_ci [[stage(fragment)]] 1350cb93a386Sopenharmony_ci fn main() -> [[location(0)]] u32 { 1351cb93a386Sopenharmony_ci return 1u; 1352cb93a386Sopenharmony_ci })"); 1353cb93a386Sopenharmony_ci } 1354cb93a386Sopenharmony_ci 1355cb93a386Sopenharmony_ci wgpu::DepthStencilState* depthStencil = pipelineDescriptor.EnableDepthStencil(format); 1356cb93a386Sopenharmony_ci if (depthDataTexture) { 1357cb93a386Sopenharmony_ci // Pass the depth test only if the depth is equal. 1358cb93a386Sopenharmony_ci depthStencil->depthCompare = wgpu::CompareFunction::Equal; 1359cb93a386Sopenharmony_ci 1360cb93a386Sopenharmony_ci // TODO(jiawei.shao@intel.com): The Intel Mesa Vulkan driver can't set gl_FragDepth unless 1361cb93a386Sopenharmony_ci // depthWriteEnabled == true. This either needs to be fixed in the driver or restricted by 1362cb93a386Sopenharmony_ci // the WebGPU API. 1363cb93a386Sopenharmony_ci depthStencil->depthWriteEnabled = true; 1364cb93a386Sopenharmony_ci } 1365cb93a386Sopenharmony_ci 1366cb93a386Sopenharmony_ci if (expectedStencil != nullptr) { 1367cb93a386Sopenharmony_ci // Pass the stencil test only if the stencil is equal. 1368cb93a386Sopenharmony_ci depthStencil->stencilFront.compare = wgpu::CompareFunction::Equal; 1369cb93a386Sopenharmony_ci } 1370cb93a386Sopenharmony_ci 1371cb93a386Sopenharmony_ci pipelineDescriptor.cTargets[0].format = colorTexDesc.format; 1372cb93a386Sopenharmony_ci 1373cb93a386Sopenharmony_ci wgpu::TextureViewDescriptor viewDesc = {}; 1374cb93a386Sopenharmony_ci viewDesc.baseMipLevel = mipLevel; 1375cb93a386Sopenharmony_ci viewDesc.mipLevelCount = 1; 1376cb93a386Sopenharmony_ci viewDesc.baseArrayLayer = arrayLayer; 1377cb93a386Sopenharmony_ci viewDesc.arrayLayerCount = 1; 1378cb93a386Sopenharmony_ci 1379cb93a386Sopenharmony_ci utils::ComboRenderPassDescriptor passDescriptor({colorTexture.CreateView()}, 1380cb93a386Sopenharmony_ci texture.CreateView(&viewDesc)); 1381cb93a386Sopenharmony_ci passDescriptor.cDepthStencilAttachmentInfo.depthLoadOp = wgpu::LoadOp::Load; 1382cb93a386Sopenharmony_ci passDescriptor.cDepthStencilAttachmentInfo.stencilLoadOp = wgpu::LoadOp::Load; 1383cb93a386Sopenharmony_ci 1384cb93a386Sopenharmony_ci wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDescriptor); 1385cb93a386Sopenharmony_ci 1386cb93a386Sopenharmony_ci wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&passDescriptor); 1387cb93a386Sopenharmony_ci if (expectedStencil != nullptr) { 1388cb93a386Sopenharmony_ci pass.SetStencilReference(*expectedStencil); 1389cb93a386Sopenharmony_ci } 1390cb93a386Sopenharmony_ci pass.SetPipeline(pipeline); 1391cb93a386Sopenharmony_ci if (depthDataTexture) { 1392cb93a386Sopenharmony_ci // Bind the depth data texture. 1393cb93a386Sopenharmony_ci pass.SetBindGroup(0, utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0), 1394cb93a386Sopenharmony_ci {{0, depthDataTexture.CreateView()}})); 1395cb93a386Sopenharmony_ci } 1396cb93a386Sopenharmony_ci pass.Draw(3); 1397cb93a386Sopenharmony_ci pass.EndPass(); 1398cb93a386Sopenharmony_ci 1399cb93a386Sopenharmony_ci wgpu::CommandBuffer commands = commandEncoder.Finish(); 1400cb93a386Sopenharmony_ci queue.Submit(1, &commands); 1401cb93a386Sopenharmony_ci 1402cb93a386Sopenharmony_ci std::vector<uint32_t> colorData(width * height, 1u); 1403cb93a386Sopenharmony_ci return EXPECT_TEXTURE_EQ(colorData.data(), colorTexture, {0, 0}, {width, height}); 1404cb93a386Sopenharmony_ci} 1405cb93a386Sopenharmony_ci 1406cb93a386Sopenharmony_civoid DawnTestBase::WaitABit() { 1407cb93a386Sopenharmony_ci device.Tick(); 1408cb93a386Sopenharmony_ci FlushWire(); 1409cb93a386Sopenharmony_ci 1410cb93a386Sopenharmony_ci utils::USleep(100); 1411cb93a386Sopenharmony_ci} 1412cb93a386Sopenharmony_ci 1413cb93a386Sopenharmony_civoid DawnTestBase::FlushWire() { 1414cb93a386Sopenharmony_ci if (gTestEnv->UsesWire()) { 1415cb93a386Sopenharmony_ci bool C2SFlushed = mWireHelper->FlushClient(); 1416cb93a386Sopenharmony_ci bool S2CFlushed = mWireHelper->FlushServer(); 1417cb93a386Sopenharmony_ci ASSERT(C2SFlushed); 1418cb93a386Sopenharmony_ci ASSERT(S2CFlushed); 1419cb93a386Sopenharmony_ci } 1420cb93a386Sopenharmony_ci} 1421cb93a386Sopenharmony_ci 1422cb93a386Sopenharmony_civoid DawnTestBase::WaitForAllOperations() { 1423cb93a386Sopenharmony_ci bool done = false; 1424cb93a386Sopenharmony_ci device.GetQueue().OnSubmittedWorkDone( 1425cb93a386Sopenharmony_ci 0u, [](WGPUQueueWorkDoneStatus, void* userdata) { *static_cast<bool*>(userdata) = true; }, 1426cb93a386Sopenharmony_ci &done); 1427cb93a386Sopenharmony_ci while (!done) { 1428cb93a386Sopenharmony_ci WaitABit(); 1429cb93a386Sopenharmony_ci } 1430cb93a386Sopenharmony_ci} 1431cb93a386Sopenharmony_ci 1432cb93a386Sopenharmony_ciDawnTestBase::ReadbackReservation DawnTestBase::ReserveReadback(uint64_t readbackSize) { 1433cb93a386Sopenharmony_ci ReadbackSlot slot; 1434cb93a386Sopenharmony_ci slot.bufferSize = readbackSize; 1435cb93a386Sopenharmony_ci 1436cb93a386Sopenharmony_ci // Create and initialize the slot buffer so that it won't unexpectedly affect the count of 1437cb93a386Sopenharmony_ci // resource lazy clear in the tests. 1438cb93a386Sopenharmony_ci const std::vector<uint8_t> initialBufferData(readbackSize, 0u); 1439cb93a386Sopenharmony_ci slot.buffer = 1440cb93a386Sopenharmony_ci utils::CreateBufferFromData(device, initialBufferData.data(), readbackSize, 1441cb93a386Sopenharmony_ci wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst); 1442cb93a386Sopenharmony_ci 1443cb93a386Sopenharmony_ci ReadbackReservation reservation; 1444cb93a386Sopenharmony_ci reservation.buffer = slot.buffer; 1445cb93a386Sopenharmony_ci reservation.slot = mReadbackSlots.size(); 1446cb93a386Sopenharmony_ci reservation.offset = 0; 1447cb93a386Sopenharmony_ci 1448cb93a386Sopenharmony_ci mReadbackSlots.push_back(std::move(slot)); 1449cb93a386Sopenharmony_ci return reservation; 1450cb93a386Sopenharmony_ci} 1451cb93a386Sopenharmony_ci 1452cb93a386Sopenharmony_civoid DawnTestBase::MapSlotsSynchronously() { 1453cb93a386Sopenharmony_ci // Initialize numPendingMapOperations before mapping, just in case the callback is called 1454cb93a386Sopenharmony_ci // immediately. 1455cb93a386Sopenharmony_ci mNumPendingMapOperations = mReadbackSlots.size(); 1456cb93a386Sopenharmony_ci 1457cb93a386Sopenharmony_ci // Map all readback slots 1458cb93a386Sopenharmony_ci for (size_t i = 0; i < mReadbackSlots.size(); ++i) { 1459cb93a386Sopenharmony_ci MapReadUserdata* userdata = new MapReadUserdata{this, i}; 1460cb93a386Sopenharmony_ci 1461cb93a386Sopenharmony_ci const ReadbackSlot& slot = mReadbackSlots[i]; 1462cb93a386Sopenharmony_ci slot.buffer.MapAsync(wgpu::MapMode::Read, 0, wgpu::kWholeMapSize, SlotMapCallback, 1463cb93a386Sopenharmony_ci userdata); 1464cb93a386Sopenharmony_ci } 1465cb93a386Sopenharmony_ci 1466cb93a386Sopenharmony_ci // Busy wait until all map operations are done. 1467cb93a386Sopenharmony_ci while (mNumPendingMapOperations != 0) { 1468cb93a386Sopenharmony_ci WaitABit(); 1469cb93a386Sopenharmony_ci } 1470cb93a386Sopenharmony_ci} 1471cb93a386Sopenharmony_ci 1472cb93a386Sopenharmony_ci// static 1473cb93a386Sopenharmony_civoid DawnTestBase::SlotMapCallback(WGPUBufferMapAsyncStatus status, void* userdata_) { 1474cb93a386Sopenharmony_ci DAWN_ASSERT(status == WGPUBufferMapAsyncStatus_Success); 1475cb93a386Sopenharmony_ci 1476cb93a386Sopenharmony_ci std::unique_ptr<MapReadUserdata> userdata(static_cast<MapReadUserdata*>(userdata_)); 1477cb93a386Sopenharmony_ci DawnTestBase* test = userdata->test; 1478cb93a386Sopenharmony_ci ReadbackSlot* slot = &test->mReadbackSlots[userdata->slot]; 1479cb93a386Sopenharmony_ci 1480cb93a386Sopenharmony_ci slot->mappedData = slot->buffer.GetConstMappedRange(); 1481cb93a386Sopenharmony_ci test->mNumPendingMapOperations--; 1482cb93a386Sopenharmony_ci} 1483cb93a386Sopenharmony_ci 1484cb93a386Sopenharmony_civoid DawnTestBase::ResolveExpectations() { 1485cb93a386Sopenharmony_ci for (const auto& expectation : mDeferredExpectations) { 1486cb93a386Sopenharmony_ci DAWN_ASSERT(mReadbackSlots[expectation.readbackSlot].mappedData != nullptr); 1487cb93a386Sopenharmony_ci 1488cb93a386Sopenharmony_ci // Get a pointer to the mapped copy of the data for the expectation. 1489cb93a386Sopenharmony_ci const char* data = 1490cb93a386Sopenharmony_ci static_cast<const char*>(mReadbackSlots[expectation.readbackSlot].mappedData); 1491cb93a386Sopenharmony_ci data += expectation.readbackOffset; 1492cb93a386Sopenharmony_ci 1493cb93a386Sopenharmony_ci uint32_t size; 1494cb93a386Sopenharmony_ci std::vector<char> packedData; 1495cb93a386Sopenharmony_ci if (expectation.rowBytes != expectation.bytesPerRow) { 1496cb93a386Sopenharmony_ci DAWN_ASSERT(expectation.bytesPerRow > expectation.rowBytes); 1497cb93a386Sopenharmony_ci uint32_t rowCount = 1498cb93a386Sopenharmony_ci (expectation.size + expectation.bytesPerRow - 1) / expectation.bytesPerRow; 1499cb93a386Sopenharmony_ci uint32_t packedSize = rowCount * expectation.rowBytes; 1500cb93a386Sopenharmony_ci packedData.resize(packedSize); 1501cb93a386Sopenharmony_ci for (uint32_t r = 0; r < rowCount; ++r) { 1502cb93a386Sopenharmony_ci for (uint32_t i = 0; i < expectation.rowBytes; ++i) { 1503cb93a386Sopenharmony_ci packedData[i + r * expectation.rowBytes] = 1504cb93a386Sopenharmony_ci data[i + r * expectation.bytesPerRow]; 1505cb93a386Sopenharmony_ci } 1506cb93a386Sopenharmony_ci } 1507cb93a386Sopenharmony_ci data = packedData.data(); 1508cb93a386Sopenharmony_ci size = packedSize; 1509cb93a386Sopenharmony_ci } else { 1510cb93a386Sopenharmony_ci size = expectation.size; 1511cb93a386Sopenharmony_ci } 1512cb93a386Sopenharmony_ci 1513cb93a386Sopenharmony_ci // Get the result for the expectation and add context to failures 1514cb93a386Sopenharmony_ci testing::AssertionResult result = expectation.expectation->Check(data, size); 1515cb93a386Sopenharmony_ci if (!result) { 1516cb93a386Sopenharmony_ci result << " Expectation created at " << expectation.file << ":" << expectation.line 1517cb93a386Sopenharmony_ci << std::endl; 1518cb93a386Sopenharmony_ci result << expectation.message->str(); 1519cb93a386Sopenharmony_ci } 1520cb93a386Sopenharmony_ci 1521cb93a386Sopenharmony_ci EXPECT_TRUE(result); 1522cb93a386Sopenharmony_ci } 1523cb93a386Sopenharmony_ci} 1524cb93a386Sopenharmony_ci 1525cb93a386Sopenharmony_cistd::unique_ptr<dawn_platform::Platform> DawnTestBase::CreateTestPlatform() { 1526cb93a386Sopenharmony_ci return nullptr; 1527cb93a386Sopenharmony_ci} 1528cb93a386Sopenharmony_ci 1529cb93a386Sopenharmony_cibool RGBA8::operator==(const RGBA8& other) const { 1530cb93a386Sopenharmony_ci return r == other.r && g == other.g && b == other.b && a == other.a; 1531cb93a386Sopenharmony_ci} 1532cb93a386Sopenharmony_ci 1533cb93a386Sopenharmony_cibool RGBA8::operator!=(const RGBA8& other) const { 1534cb93a386Sopenharmony_ci return !(*this == other); 1535cb93a386Sopenharmony_ci} 1536cb93a386Sopenharmony_ci 1537cb93a386Sopenharmony_cibool RGBA8::operator<=(const RGBA8& other) const { 1538cb93a386Sopenharmony_ci return (r <= other.r && g <= other.g && b <= other.b && a <= other.a); 1539cb93a386Sopenharmony_ci} 1540cb93a386Sopenharmony_ci 1541cb93a386Sopenharmony_cibool RGBA8::operator>=(const RGBA8& other) const { 1542cb93a386Sopenharmony_ci return (r >= other.r && g >= other.g && b >= other.b && a >= other.a); 1543cb93a386Sopenharmony_ci} 1544cb93a386Sopenharmony_ci 1545cb93a386Sopenharmony_cistd::ostream& operator<<(std::ostream& stream, const RGBA8& color) { 1546cb93a386Sopenharmony_ci return stream << "RGBA8(" << static_cast<int>(color.r) << ", " << static_cast<int>(color.g) 1547cb93a386Sopenharmony_ci << ", " << static_cast<int>(color.b) << ", " << static_cast<int>(color.a) << ")"; 1548cb93a386Sopenharmony_ci} 1549cb93a386Sopenharmony_ci 1550cb93a386Sopenharmony_cinamespace detail { 1551cb93a386Sopenharmony_ci std::vector<AdapterTestParam> GetAvailableAdapterTestParamsForBackends( 1552cb93a386Sopenharmony_ci const BackendTestConfig* params, 1553cb93a386Sopenharmony_ci size_t numParams) { 1554cb93a386Sopenharmony_ci ASSERT(gTestEnv != nullptr); 1555cb93a386Sopenharmony_ci return gTestEnv->GetAvailableAdapterTestParamsForBackends(params, numParams); 1556cb93a386Sopenharmony_ci } 1557cb93a386Sopenharmony_ci 1558cb93a386Sopenharmony_ci // Helper classes to set expectations 1559cb93a386Sopenharmony_ci 1560cb93a386Sopenharmony_ci template <typename T, typename U> 1561cb93a386Sopenharmony_ci ExpectEq<T, U>::ExpectEq(T singleValue, T tolerance) : mTolerance(tolerance) { 1562cb93a386Sopenharmony_ci mExpected.push_back(singleValue); 1563cb93a386Sopenharmony_ci } 1564cb93a386Sopenharmony_ci 1565cb93a386Sopenharmony_ci template <typename T, typename U> 1566cb93a386Sopenharmony_ci ExpectEq<T, U>::ExpectEq(const T* values, const unsigned int count, T tolerance) 1567cb93a386Sopenharmony_ci : mTolerance(tolerance) { 1568cb93a386Sopenharmony_ci mExpected.assign(values, values + count); 1569cb93a386Sopenharmony_ci } 1570cb93a386Sopenharmony_ci 1571cb93a386Sopenharmony_ci namespace { 1572cb93a386Sopenharmony_ci 1573cb93a386Sopenharmony_ci template <typename T, typename U = T> 1574cb93a386Sopenharmony_ci testing::AssertionResult CheckImpl(const T& expected, const U& actual, const T& tolerance) { 1575cb93a386Sopenharmony_ci ASSERT(tolerance == T{}); 1576cb93a386Sopenharmony_ci if (expected != actual) { 1577cb93a386Sopenharmony_ci return testing::AssertionFailure() << expected << ", actual " << actual; 1578cb93a386Sopenharmony_ci } 1579cb93a386Sopenharmony_ci return testing::AssertionSuccess(); 1580cb93a386Sopenharmony_ci } 1581cb93a386Sopenharmony_ci 1582cb93a386Sopenharmony_ci template <> 1583cb93a386Sopenharmony_ci testing::AssertionResult CheckImpl<float>(const float& expected, 1584cb93a386Sopenharmony_ci const float& actual, 1585cb93a386Sopenharmony_ci const float& tolerance) { 1586cb93a386Sopenharmony_ci if (abs(expected - actual) > tolerance) { 1587cb93a386Sopenharmony_ci return tolerance == 0.0 1588cb93a386Sopenharmony_ci ? testing::AssertionFailure() << expected << ", actual " << actual 1589cb93a386Sopenharmony_ci : testing::AssertionFailure() << "within " << tolerance << " of " 1590cb93a386Sopenharmony_ci << expected << ", actual " << actual; 1591cb93a386Sopenharmony_ci } 1592cb93a386Sopenharmony_ci return testing::AssertionSuccess(); 1593cb93a386Sopenharmony_ci } 1594cb93a386Sopenharmony_ci 1595cb93a386Sopenharmony_ci // Interpret uint16_t as float16 1596cb93a386Sopenharmony_ci // This is mostly for reading float16 output from textures 1597cb93a386Sopenharmony_ci template <> 1598cb93a386Sopenharmony_ci testing::AssertionResult CheckImpl<float, uint16_t>(const float& expected, 1599cb93a386Sopenharmony_ci const uint16_t& actual, 1600cb93a386Sopenharmony_ci const float& tolerance) { 1601cb93a386Sopenharmony_ci float actualF32 = Float16ToFloat32(actual); 1602cb93a386Sopenharmony_ci if (abs(expected - actualF32) > tolerance) { 1603cb93a386Sopenharmony_ci return tolerance == 0.0 1604cb93a386Sopenharmony_ci ? testing::AssertionFailure() << expected << ", actual " << actualF32 1605cb93a386Sopenharmony_ci : testing::AssertionFailure() << "within " << tolerance << " of " 1606cb93a386Sopenharmony_ci << expected << ", actual " << actualF32; 1607cb93a386Sopenharmony_ci } 1608cb93a386Sopenharmony_ci return testing::AssertionSuccess(); 1609cb93a386Sopenharmony_ci } 1610cb93a386Sopenharmony_ci 1611cb93a386Sopenharmony_ci } // namespace 1612cb93a386Sopenharmony_ci 1613cb93a386Sopenharmony_ci template <typename T, typename U> 1614cb93a386Sopenharmony_ci testing::AssertionResult ExpectEq<T, U>::Check(const void* data, size_t size) { 1615cb93a386Sopenharmony_ci DAWN_ASSERT(size == sizeof(U) * mExpected.size()); 1616cb93a386Sopenharmony_ci const U* actual = static_cast<const U*>(data); 1617cb93a386Sopenharmony_ci 1618cb93a386Sopenharmony_ci for (size_t i = 0; i < mExpected.size(); ++i) { 1619cb93a386Sopenharmony_ci testing::AssertionResult check = CheckImpl(mExpected[i], actual[i], mTolerance); 1620cb93a386Sopenharmony_ci if (!check) { 1621cb93a386Sopenharmony_ci testing::AssertionResult result = testing::AssertionFailure() 1622cb93a386Sopenharmony_ci << "Expected data[" << i << "] to be " 1623cb93a386Sopenharmony_ci << check.message() << std::endl; 1624cb93a386Sopenharmony_ci 1625cb93a386Sopenharmony_ci if (mExpected.size() <= 1024) { 1626cb93a386Sopenharmony_ci result << "Expected:" << std::endl; 1627cb93a386Sopenharmony_ci printBuffer(result, mExpected.data(), mExpected.size()); 1628cb93a386Sopenharmony_ci 1629cb93a386Sopenharmony_ci result << "Actual:" << std::endl; 1630cb93a386Sopenharmony_ci printBuffer(result, actual, mExpected.size()); 1631cb93a386Sopenharmony_ci } 1632cb93a386Sopenharmony_ci 1633cb93a386Sopenharmony_ci return result; 1634cb93a386Sopenharmony_ci } 1635cb93a386Sopenharmony_ci } 1636cb93a386Sopenharmony_ci return testing::AssertionSuccess(); 1637cb93a386Sopenharmony_ci } 1638cb93a386Sopenharmony_ci 1639cb93a386Sopenharmony_ci template class ExpectEq<uint8_t>; 1640cb93a386Sopenharmony_ci template class ExpectEq<uint16_t>; 1641cb93a386Sopenharmony_ci template class ExpectEq<uint32_t>; 1642cb93a386Sopenharmony_ci template class ExpectEq<uint64_t>; 1643cb93a386Sopenharmony_ci template class ExpectEq<RGBA8>; 1644cb93a386Sopenharmony_ci template class ExpectEq<float>; 1645cb93a386Sopenharmony_ci template class ExpectEq<float, uint16_t>; 1646cb93a386Sopenharmony_ci 1647cb93a386Sopenharmony_ci template <typename T> 1648cb93a386Sopenharmony_ci ExpectBetweenColors<T>::ExpectBetweenColors(T value0, T value1) { 1649cb93a386Sopenharmony_ci T l, h; 1650cb93a386Sopenharmony_ci l.r = std::min(value0.r, value1.r); 1651cb93a386Sopenharmony_ci l.g = std::min(value0.g, value1.g); 1652cb93a386Sopenharmony_ci l.b = std::min(value0.b, value1.b); 1653cb93a386Sopenharmony_ci l.a = std::min(value0.a, value1.a); 1654cb93a386Sopenharmony_ci 1655cb93a386Sopenharmony_ci h.r = std::max(value0.r, value1.r); 1656cb93a386Sopenharmony_ci h.g = std::max(value0.g, value1.g); 1657cb93a386Sopenharmony_ci h.b = std::max(value0.b, value1.b); 1658cb93a386Sopenharmony_ci h.a = std::max(value0.a, value1.a); 1659cb93a386Sopenharmony_ci 1660cb93a386Sopenharmony_ci mLowerColorChannels.push_back(l); 1661cb93a386Sopenharmony_ci mHigherColorChannels.push_back(h); 1662cb93a386Sopenharmony_ci 1663cb93a386Sopenharmony_ci mValues0.push_back(value0); 1664cb93a386Sopenharmony_ci mValues1.push_back(value1); 1665cb93a386Sopenharmony_ci } 1666cb93a386Sopenharmony_ci 1667cb93a386Sopenharmony_ci template <typename T> 1668cb93a386Sopenharmony_ci testing::AssertionResult ExpectBetweenColors<T>::Check(const void* data, size_t size) { 1669cb93a386Sopenharmony_ci DAWN_ASSERT(size == sizeof(T) * mLowerColorChannels.size()); 1670cb93a386Sopenharmony_ci DAWN_ASSERT(mHigherColorChannels.size() == mLowerColorChannels.size()); 1671cb93a386Sopenharmony_ci DAWN_ASSERT(mValues0.size() == mValues1.size()); 1672cb93a386Sopenharmony_ci DAWN_ASSERT(mValues0.size() == mLowerColorChannels.size()); 1673cb93a386Sopenharmony_ci 1674cb93a386Sopenharmony_ci const T* actual = static_cast<const T*>(data); 1675cb93a386Sopenharmony_ci 1676cb93a386Sopenharmony_ci for (size_t i = 0; i < mLowerColorChannels.size(); ++i) { 1677cb93a386Sopenharmony_ci if (!(actual[i] >= mLowerColorChannels[i] && actual[i] <= mHigherColorChannels[i])) { 1678cb93a386Sopenharmony_ci testing::AssertionResult result = testing::AssertionFailure() 1679cb93a386Sopenharmony_ci << "Expected data[" << i << "] to be between " 1680cb93a386Sopenharmony_ci << mValues0[i] << " and " << mValues1[i] 1681cb93a386Sopenharmony_ci << ", actual " << actual[i] << std::endl; 1682cb93a386Sopenharmony_ci 1683cb93a386Sopenharmony_ci if (mLowerColorChannels.size() <= 1024) { 1684cb93a386Sopenharmony_ci result << "Expected between:" << std::endl; 1685cb93a386Sopenharmony_ci printBuffer(result, mValues0.data(), mLowerColorChannels.size()); 1686cb93a386Sopenharmony_ci result << "and" << std::endl; 1687cb93a386Sopenharmony_ci printBuffer(result, mValues1.data(), mLowerColorChannels.size()); 1688cb93a386Sopenharmony_ci 1689cb93a386Sopenharmony_ci result << "Actual:" << std::endl; 1690cb93a386Sopenharmony_ci printBuffer(result, actual, mLowerColorChannels.size()); 1691cb93a386Sopenharmony_ci } 1692cb93a386Sopenharmony_ci 1693cb93a386Sopenharmony_ci return result; 1694cb93a386Sopenharmony_ci } 1695cb93a386Sopenharmony_ci } 1696cb93a386Sopenharmony_ci 1697cb93a386Sopenharmony_ci return testing::AssertionSuccess(); 1698cb93a386Sopenharmony_ci } 1699cb93a386Sopenharmony_ci 1700cb93a386Sopenharmony_ci template class ExpectBetweenColors<RGBA8>; 1701cb93a386Sopenharmony_ci} // namespace detail 1702