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, &copyExtent);
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