2018-07-18 09:40:26 +00:00
|
|
|
// Copyright 2017 The Dawn Authors
|
2017-06-16 22:34:35 +00:00
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2018-07-18 13:18:25 +00:00
|
|
|
#include "tests/DawnTest.h"
|
2017-06-16 22:34:35 +00:00
|
|
|
|
2017-07-10 17:46:05 +00:00
|
|
|
#include "common/Assert.h"
|
2020-01-07 17:49:15 +00:00
|
|
|
#include "common/GPUInfo.h"
|
2019-12-05 11:13:01 +00:00
|
|
|
#include "common/Log.h"
|
2017-07-13 19:10:30 +00:00
|
|
|
#include "common/Math.h"
|
2018-09-19 00:32:52 +00:00
|
|
|
#include "common/Platform.h"
|
2019-12-10 23:32:48 +00:00
|
|
|
#include "common/SystemUtils.h"
|
2019-10-15 11:44:38 +00:00
|
|
|
#include "dawn/dawn_proc.h"
|
2018-08-02 20:27:57 +00:00
|
|
|
#include "dawn_native/DawnNative.h"
|
2019-02-11 21:50:16 +00:00
|
|
|
#include "dawn_wire/WireClient.h"
|
|
|
|
#include "dawn_wire/WireServer.h"
|
2020-08-14 21:02:12 +00:00
|
|
|
#include "utils/PlatformDebugLogger.h"
|
2017-07-17 21:13:57 +00:00
|
|
|
#include "utils/SystemUtils.h"
|
2018-07-26 13:07:57 +00:00
|
|
|
#include "utils/TerribleCommandBuffer.h"
|
2020-10-23 21:21:33 +00:00
|
|
|
#include "utils/TestUtils.h"
|
2019-10-25 11:36:47 +00:00
|
|
|
#include "utils/WGPUHelpers.h"
|
2017-06-16 22:34:35 +00:00
|
|
|
|
2019-02-12 15:48:15 +00:00
|
|
|
#include <algorithm>
|
2019-12-10 23:32:48 +00:00
|
|
|
#include <fstream>
|
2019-02-21 17:36:11 +00:00
|
|
|
#include <iomanip>
|
2020-05-15 20:28:05 +00:00
|
|
|
#include <regex>
|
2019-02-21 17:36:11 +00:00
|
|
|
#include <sstream>
|
2019-02-05 12:17:20 +00:00
|
|
|
#include <unordered_map>
|
2019-08-13 21:45:44 +00:00
|
|
|
|
2020-08-14 21:02:12 +00:00
|
|
|
#if defined(DAWN_ENABLE_BACKEND_OPENGL)
|
2019-08-13 21:45:44 +00:00
|
|
|
# include "GLFW/glfw3.h"
|
|
|
|
# include "dawn_native/OpenGLBackend.h"
|
|
|
|
#endif // DAWN_ENABLE_BACKEND_OPENGL
|
2018-06-07 11:10:44 +00:00
|
|
|
|
2017-06-16 22:34:35 +00:00
|
|
|
namespace {
|
|
|
|
|
2020-01-10 13:28:18 +00:00
|
|
|
std::string ParamName(wgpu::BackendType type) {
|
2018-07-18 13:18:25 +00:00
|
|
|
switch (type) {
|
2020-01-10 13:28:18 +00:00
|
|
|
case wgpu::BackendType::D3D12:
|
2017-06-16 22:34:35 +00:00
|
|
|
return "D3D12";
|
2020-01-10 13:28:18 +00:00
|
|
|
case wgpu::BackendType::Metal:
|
2017-06-16 22:34:35 +00:00
|
|
|
return "Metal";
|
2020-01-10 13:28:18 +00:00
|
|
|
case wgpu::BackendType::Null:
|
2019-02-05 12:17:20 +00:00
|
|
|
return "Null";
|
2020-01-10 13:28:18 +00:00
|
|
|
case wgpu::BackendType::OpenGL:
|
2017-06-16 22:34:35 +00:00
|
|
|
return "OpenGL";
|
2020-11-25 16:45:04 +00:00
|
|
|
case wgpu::BackendType::OpenGLES:
|
|
|
|
return "OpenGLES";
|
2020-01-10 13:28:18 +00:00
|
|
|
case wgpu::BackendType::Vulkan:
|
2017-06-16 22:34:35 +00:00
|
|
|
return "Vulkan";
|
|
|
|
default:
|
2017-07-11 01:48:12 +00:00
|
|
|
UNREACHABLE();
|
2017-06-16 22:34:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-10 13:28:18 +00:00
|
|
|
const char* AdapterTypeName(wgpu::AdapterType type) {
|
2019-04-15 16:36:25 +00:00
|
|
|
switch (type) {
|
2020-01-10 13:28:18 +00:00
|
|
|
case wgpu::AdapterType::DiscreteGPU:
|
2019-04-15 16:36:25 +00:00
|
|
|
return "Discrete GPU";
|
2020-01-10 13:28:18 +00:00
|
|
|
case wgpu::AdapterType::IntegratedGPU:
|
2019-04-15 16:36:25 +00:00
|
|
|
return "Integrated GPU";
|
2020-01-10 13:28:18 +00:00
|
|
|
case wgpu::AdapterType::CPU:
|
2019-04-15 16:36:25 +00:00
|
|
|
return "CPU";
|
2020-01-10 13:28:18 +00:00
|
|
|
case wgpu::AdapterType::Unknown:
|
2019-04-15 16:36:25 +00:00
|
|
|
return "Unknown";
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-16 22:34:35 +00:00
|
|
|
struct MapReadUserdata {
|
2019-08-28 23:18:10 +00:00
|
|
|
DawnTestBase* test;
|
2017-06-16 22:34:35 +00:00
|
|
|
size_t slot;
|
|
|
|
};
|
2018-10-16 09:16:15 +00:00
|
|
|
|
2019-02-21 16:29:12 +00:00
|
|
|
DawnTestEnvironment* gTestEnv = nullptr;
|
|
|
|
|
2020-12-24 03:11:17 +00:00
|
|
|
template <typename T>
|
|
|
|
void printBuffer(testing::AssertionResult& result, const T* buffer, const size_t count) {
|
|
|
|
static constexpr unsigned int kBytes = sizeof(T);
|
|
|
|
|
|
|
|
for (size_t index = 0; index < count; ++index) {
|
|
|
|
auto byteView = reinterpret_cast<const uint8_t*>(buffer + index);
|
|
|
|
for (unsigned int b = 0; b < kBytes; ++b) {
|
|
|
|
char buf[4];
|
|
|
|
sprintf(buf, "%02X ", byteView[b]);
|
|
|
|
result << buf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
result << std::endl;
|
|
|
|
}
|
|
|
|
|
2020-08-14 21:02:12 +00:00
|
|
|
} // anonymous namespace
|
2017-06-16 22:34:35 +00:00
|
|
|
|
2019-11-19 17:57:30 +00:00
|
|
|
const RGBA8 RGBA8::kZero = RGBA8(0, 0, 0, 0);
|
|
|
|
const RGBA8 RGBA8::kBlack = RGBA8(0, 0, 0, 255);
|
|
|
|
const RGBA8 RGBA8::kRed = RGBA8(255, 0, 0, 255);
|
|
|
|
const RGBA8 RGBA8::kGreen = RGBA8(0, 255, 0, 255);
|
|
|
|
const RGBA8 RGBA8::kBlue = RGBA8(0, 0, 255, 255);
|
|
|
|
const RGBA8 RGBA8::kYellow = RGBA8(255, 255, 0, 255);
|
|
|
|
const RGBA8 RGBA8::kWhite = RGBA8(255, 255, 255, 255);
|
|
|
|
|
2020-05-15 20:28:05 +00:00
|
|
|
BackendTestConfig::BackendTestConfig(wgpu::BackendType backendType,
|
|
|
|
std::initializer_list<const char*> forceEnabledWorkarounds,
|
|
|
|
std::initializer_list<const char*> forceDisabledWorkarounds)
|
2020-02-25 16:23:17 +00:00
|
|
|
: backendType(backendType),
|
|
|
|
forceEnabledWorkarounds(forceEnabledWorkarounds),
|
|
|
|
forceDisabledWorkarounds(forceDisabledWorkarounds) {
|
|
|
|
}
|
|
|
|
|
2020-05-15 20:28:05 +00:00
|
|
|
BackendTestConfig D3D12Backend(std::initializer_list<const char*> forceEnabledWorkarounds,
|
|
|
|
std::initializer_list<const char*> forceDisabledWorkarounds) {
|
|
|
|
return BackendTestConfig(wgpu::BackendType::D3D12, forceEnabledWorkarounds,
|
|
|
|
forceDisabledWorkarounds);
|
2020-02-25 16:23:17 +00:00
|
|
|
}
|
2019-05-29 00:07:37 +00:00
|
|
|
|
2020-05-15 20:28:05 +00:00
|
|
|
BackendTestConfig MetalBackend(std::initializer_list<const char*> forceEnabledWorkarounds,
|
|
|
|
std::initializer_list<const char*> forceDisabledWorkarounds) {
|
|
|
|
return BackendTestConfig(wgpu::BackendType::Metal, forceEnabledWorkarounds,
|
|
|
|
forceDisabledWorkarounds);
|
2020-02-25 16:23:17 +00:00
|
|
|
}
|
|
|
|
|
2020-05-15 20:28:05 +00:00
|
|
|
BackendTestConfig NullBackend(std::initializer_list<const char*> forceEnabledWorkarounds,
|
|
|
|
std::initializer_list<const char*> forceDisabledWorkarounds) {
|
|
|
|
return BackendTestConfig(wgpu::BackendType::Null, forceEnabledWorkarounds,
|
|
|
|
forceDisabledWorkarounds);
|
2020-03-20 17:07:20 +00:00
|
|
|
}
|
|
|
|
|
2020-05-15 20:28:05 +00:00
|
|
|
BackendTestConfig OpenGLBackend(std::initializer_list<const char*> forceEnabledWorkarounds,
|
|
|
|
std::initializer_list<const char*> forceDisabledWorkarounds) {
|
|
|
|
return BackendTestConfig(wgpu::BackendType::OpenGL, forceEnabledWorkarounds,
|
|
|
|
forceDisabledWorkarounds);
|
2020-02-25 16:23:17 +00:00
|
|
|
}
|
|
|
|
|
2020-11-25 16:45:04 +00:00
|
|
|
BackendTestConfig OpenGLESBackend(std::initializer_list<const char*> forceEnabledWorkarounds,
|
|
|
|
std::initializer_list<const char*> forceDisabledWorkarounds) {
|
|
|
|
return BackendTestConfig(wgpu::BackendType::OpenGLES, forceEnabledWorkarounds,
|
|
|
|
forceDisabledWorkarounds);
|
|
|
|
}
|
|
|
|
|
2020-05-15 20:28:05 +00:00
|
|
|
BackendTestConfig VulkanBackend(std::initializer_list<const char*> forceEnabledWorkarounds,
|
|
|
|
std::initializer_list<const char*> forceDisabledWorkarounds) {
|
|
|
|
return BackendTestConfig(wgpu::BackendType::Vulkan, forceEnabledWorkarounds,
|
|
|
|
forceDisabledWorkarounds);
|
2019-04-26 07:52:57 +00:00
|
|
|
}
|
|
|
|
|
2020-05-15 16:07:12 +00:00
|
|
|
TestAdapterProperties::TestAdapterProperties(const wgpu::AdapterProperties& properties,
|
|
|
|
bool selected)
|
|
|
|
: wgpu::AdapterProperties(properties), adapterName(properties.name), selected(selected) {
|
|
|
|
}
|
|
|
|
|
2020-05-15 20:28:05 +00:00
|
|
|
AdapterTestParam::AdapterTestParam(const BackendTestConfig& config,
|
|
|
|
const TestAdapterProperties& adapterProperties)
|
|
|
|
: adapterProperties(adapterProperties),
|
|
|
|
forceEnabledWorkarounds(config.forceEnabledWorkarounds),
|
|
|
|
forceDisabledWorkarounds(config.forceDisabledWorkarounds) {
|
|
|
|
}
|
|
|
|
|
|
|
|
std::ostream& operator<<(std::ostream& os, const AdapterTestParam& param) {
|
|
|
|
// Sanitize the adapter name for GoogleTest
|
|
|
|
std::string sanitizedName =
|
|
|
|
std::regex_replace(param.adapterProperties.adapterName, std::regex("[^a-zA-Z0-9]+"), "_");
|
|
|
|
|
|
|
|
// Strip trailing underscores, if any.
|
|
|
|
if (sanitizedName.back() == '_') {
|
|
|
|
sanitizedName.back() = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
os << ParamName(param.adapterProperties.backendType) << "_" << sanitizedName.c_str();
|
2020-05-21 00:24:16 +00:00
|
|
|
|
|
|
|
// In a Windows Remote Desktop session there are two adapters named "Microsoft Basic Render
|
|
|
|
// Driver" with different adapter types. We must differentiate them to avoid any tests using the
|
|
|
|
// same name.
|
|
|
|
if (param.adapterProperties.deviceID == 0x008C) {
|
|
|
|
std::string adapterType = AdapterTypeName(param.adapterProperties.adapterType);
|
|
|
|
std::replace(adapterType.begin(), adapterType.end(), ' ', '_');
|
|
|
|
os << "_" << adapterType;
|
|
|
|
}
|
|
|
|
|
2019-08-27 01:44:29 +00:00
|
|
|
for (const char* forceEnabledWorkaround : param.forceEnabledWorkarounds) {
|
|
|
|
os << "__e_" << forceEnabledWorkaround;
|
|
|
|
}
|
|
|
|
for (const char* forceDisabledWorkaround : param.forceDisabledWorkarounds) {
|
|
|
|
os << "__d_" << forceDisabledWorkaround;
|
|
|
|
}
|
|
|
|
return os;
|
|
|
|
}
|
|
|
|
|
2019-02-21 16:29:12 +00:00
|
|
|
// Implementation of DawnTestEnvironment
|
|
|
|
|
|
|
|
void InitDawnEnd2EndTestEnvironment(int argc, char** argv) {
|
|
|
|
gTestEnv = new DawnTestEnvironment(argc, argv);
|
|
|
|
testing::AddGlobalTestEnvironment(gTestEnv);
|
|
|
|
}
|
|
|
|
|
2020-05-15 16:04:32 +00:00
|
|
|
// static
|
|
|
|
void DawnTestEnvironment::SetEnvironment(DawnTestEnvironment* env) {
|
|
|
|
gTestEnv = env;
|
|
|
|
}
|
|
|
|
|
2019-02-21 16:29:12 +00:00
|
|
|
DawnTestEnvironment::DawnTestEnvironment(int argc, char** argv) {
|
2020-05-15 16:07:12 +00:00
|
|
|
ParseArgs(argc, argv);
|
|
|
|
|
2020-09-22 16:23:06 +00:00
|
|
|
if (mEnableBackendValidation) {
|
|
|
|
mPlatformDebugLogger =
|
|
|
|
std::unique_ptr<utils::PlatformDebugLogger>(utils::CreatePlatformDebugLogger());
|
|
|
|
}
|
|
|
|
|
2020-05-15 20:28:05 +00:00
|
|
|
// Create a temporary instance to select available and preferred adapters. This is done before
|
|
|
|
// test instantiation so GetAvailableAdapterTestParamsForBackends can generate test
|
|
|
|
// parameterizations all selected adapters. We drop the instance at the end of this function
|
|
|
|
// because the Vulkan validation layers use static global mutexes which behave badly when
|
|
|
|
// Chromium's test launcher forks the test process. The instance will be recreated on test
|
|
|
|
// environment setup.
|
2020-05-15 16:07:12 +00:00
|
|
|
std::unique_ptr<dawn_native::Instance> instance = CreateInstanceAndDiscoverAdapters();
|
|
|
|
ASSERT(instance);
|
|
|
|
|
2020-05-15 20:28:05 +00:00
|
|
|
SelectPreferredAdapterProperties(instance.get());
|
2020-11-14 01:09:23 +00:00
|
|
|
PrintTestConfigurationAndAdapterInfo(instance.get());
|
2020-05-15 16:07:12 +00:00
|
|
|
}
|
|
|
|
|
2020-08-14 21:02:12 +00:00
|
|
|
DawnTestEnvironment::~DawnTestEnvironment() = default;
|
|
|
|
|
2020-05-15 16:07:12 +00:00
|
|
|
void DawnTestEnvironment::ParseArgs(int argc, char** argv) {
|
2020-05-15 16:04:32 +00:00
|
|
|
size_t argLen = 0; // Set when parsing --arg=X arguments
|
2019-02-21 16:29:12 +00:00
|
|
|
for (int i = 1; i < argc; ++i) {
|
|
|
|
if (strcmp("-w", argv[i]) == 0 || strcmp("--use-wire", argv[i]) == 0) {
|
|
|
|
mUseWire = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-05-15 06:06:26 +00:00
|
|
|
if (strcmp("-d", argv[i]) == 0 || strcmp("--enable-backend-validation", argv[i]) == 0) {
|
|
|
|
mEnableBackendValidation = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-06-21 02:09:05 +00:00
|
|
|
if (strcmp("-c", argv[i]) == 0 || strcmp("--begin-capture-on-startup", argv[i]) == 0) {
|
|
|
|
mBeginCaptureOnStartup = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-11-14 01:09:23 +00:00
|
|
|
constexpr const char kEnableTogglesSwitch[] = "--enable-toggles=";
|
|
|
|
argLen = sizeof(kEnableTogglesSwitch) - 1;
|
|
|
|
if (strncmp(argv[i], kEnableTogglesSwitch, argLen) == 0) {
|
|
|
|
std::string toggle;
|
|
|
|
std::stringstream toggles(argv[i] + argLen);
|
|
|
|
while (getline(toggles, toggle, ',')) {
|
|
|
|
mEnabledToggles.push_back(toggle);
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
constexpr const char kDisableTogglesSwitch[] = "--disable-toggles=";
|
|
|
|
argLen = sizeof(kDisableTogglesSwitch) - 1;
|
|
|
|
if (strncmp(argv[i], kDisableTogglesSwitch, argLen) == 0) {
|
|
|
|
std::string toggle;
|
|
|
|
std::stringstream toggles(argv[i] + argLen);
|
|
|
|
while (getline(toggles, toggle, ',')) {
|
|
|
|
mDisabledToggles.push_back(toggle);
|
|
|
|
}
|
2019-11-21 00:48:39 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-10-17 19:00:32 +00:00
|
|
|
constexpr const char kVendorIdFilterArg[] = "--adapter-vendor-id=";
|
2020-05-15 16:04:32 +00:00
|
|
|
argLen = sizeof(kVendorIdFilterArg) - 1;
|
|
|
|
if (strncmp(argv[i], kVendorIdFilterArg, argLen) == 0) {
|
|
|
|
const char* vendorIdFilter = argv[i] + argLen;
|
2019-10-17 19:00:32 +00:00
|
|
|
if (vendorIdFilter[0] != '\0') {
|
|
|
|
mVendorIdFilter = strtoul(vendorIdFilter, nullptr, 16);
|
2019-07-08 03:25:54 +00:00
|
|
|
// Set filter flag if vendor id is non-zero.
|
|
|
|
mHasVendorIdFilter = mVendorIdFilter != 0;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-05-15 20:28:05 +00:00
|
|
|
constexpr const char kExclusiveDeviceTypePreferenceArg[] =
|
|
|
|
"--exclusive-device-type-preference=";
|
|
|
|
argLen = sizeof(kExclusiveDeviceTypePreferenceArg) - 1;
|
|
|
|
if (strncmp(argv[i], kExclusiveDeviceTypePreferenceArg, argLen) == 0) {
|
|
|
|
const char* preference = argv[i] + argLen;
|
|
|
|
if (preference[0] != '\0') {
|
|
|
|
std::istringstream ss(preference);
|
|
|
|
std::string type;
|
|
|
|
while (std::getline(ss, type, ',')) {
|
|
|
|
if (strcmp(type.c_str(), "discrete") == 0) {
|
|
|
|
mDevicePreferences.push_back(dawn_native::DeviceType::DiscreteGPU);
|
|
|
|
} else if (strcmp(type.c_str(), "integrated") == 0) {
|
|
|
|
mDevicePreferences.push_back(dawn_native::DeviceType::IntegratedGPU);
|
|
|
|
} else if (strcmp(type.c_str(), "cpu") == 0) {
|
|
|
|
mDevicePreferences.push_back(dawn_native::DeviceType::CPU);
|
|
|
|
} else {
|
|
|
|
dawn::ErrorLog() << "Invalid device type preference: " << type;
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-10 23:32:48 +00:00
|
|
|
constexpr const char kWireTraceDirArg[] = "--wire-trace-dir=";
|
2020-05-15 16:04:32 +00:00
|
|
|
argLen = sizeof(kWireTraceDirArg) - 1;
|
|
|
|
if (strncmp(argv[i], kWireTraceDirArg, argLen) == 0) {
|
|
|
|
const char* wireTraceDir = argv[i] + argLen;
|
2019-12-10 23:32:48 +00:00
|
|
|
if (wireTraceDir[0] != '\0') {
|
|
|
|
const char* sep = GetPathSeparator();
|
|
|
|
mWireTraceDir = wireTraceDir;
|
|
|
|
if (mWireTraceDir.back() != *sep) {
|
|
|
|
mWireTraceDir += sep;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-02-21 16:29:12 +00:00
|
|
|
if (strcmp("-h", argv[i]) == 0 || strcmp("--help", argv[i]) == 0) {
|
2019-12-06 18:21:39 +00:00
|
|
|
dawn::InfoLog()
|
|
|
|
<< "\n\nUsage: " << argv[0]
|
2020-11-16 22:41:36 +00:00
|
|
|
<< " [GTEST_FLAGS...] [-w] [-d] [-c]\n"
|
2020-11-14 01:09:23 +00:00
|
|
|
" [--enable-toggles=toggles] [--disable-toggles=toggles]\n"
|
|
|
|
" [--adapter-vendor-id=x]"
|
|
|
|
" [--exclusive-device-type-preference=integrated,cpu,discrete]\n\n"
|
2019-12-06 18:21:39 +00:00
|
|
|
" -w, --use-wire: Run the tests through the wire (defaults to no wire)\n"
|
|
|
|
" -d, --enable-backend-validation: Enable backend validation (defaults"
|
|
|
|
" to disabled)\n"
|
|
|
|
" -c, --begin-capture-on-startup: Begin debug capture on startup "
|
|
|
|
"(defaults to no capture)\n"
|
2020-11-14 01:09:23 +00:00
|
|
|
" --enable-toggles: Comma-delimited list of Dawn toggles to enable.\n"
|
2020-11-16 22:41:36 +00:00
|
|
|
" ex.) skip_validation,use_tint_generator,disable_robustness,turn_off_vsync\n"
|
2020-11-14 01:09:23 +00:00
|
|
|
" --disable-toggles: Comma-delimited list of Dawn toggles to disable\n"
|
2019-12-06 18:21:39 +00:00
|
|
|
" --adapter-vendor-id: Select adapter by vendor id to run end2end tests"
|
2020-05-15 20:28:05 +00:00
|
|
|
"on multi-GPU systems \n"
|
|
|
|
" --exclusive-device-type-preference: Comma-delimited list of preferred device "
|
|
|
|
"types. For each backend, tests will run only on adapters that match the first "
|
|
|
|
"available device type\n";
|
2019-02-21 16:29:12 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-25 16:45:04 +00:00
|
|
|
std::unique_ptr<dawn_native::Instance> DawnTestEnvironment::CreateInstanceAndDiscoverAdapters() {
|
2020-05-15 16:04:32 +00:00
|
|
|
auto instance = std::make_unique<dawn_native::Instance>();
|
|
|
|
instance->EnableBackendValidation(mEnableBackendValidation);
|
2020-07-29 19:44:41 +00:00
|
|
|
instance->EnableGPUBasedBackendValidation(mEnableBackendValidation);
|
2020-05-15 16:04:32 +00:00
|
|
|
instance->EnableBeginCaptureOnStartup(mBeginCaptureOnStartup);
|
|
|
|
|
|
|
|
instance->DiscoverDefaultAdapters();
|
|
|
|
|
|
|
|
#ifdef DAWN_ENABLE_BACKEND_OPENGL
|
|
|
|
if (!glfwInit()) {
|
|
|
|
return instance;
|
|
|
|
}
|
|
|
|
glfwDefaultWindowHints();
|
|
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
|
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
|
|
|
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
|
|
|
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
|
|
|
|
2020-11-25 16:45:04 +00:00
|
|
|
mOpenGLWindow = glfwCreateWindow(400, 400, "Dawn OpenGL test window", nullptr, nullptr);
|
2020-05-15 16:04:32 +00:00
|
|
|
|
2020-11-25 16:45:04 +00:00
|
|
|
glfwMakeContextCurrent(mOpenGLWindow);
|
2020-05-15 16:04:32 +00:00
|
|
|
dawn_native::opengl::AdapterDiscoveryOptions adapterOptions;
|
|
|
|
adapterOptions.getProc = reinterpret_cast<void* (*)(const char*)>(glfwGetProcAddress);
|
|
|
|
instance->DiscoverAdapters(&adapterOptions);
|
2020-11-25 16:45:04 +00:00
|
|
|
|
|
|
|
glfwDefaultWindowHints();
|
|
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
|
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
|
|
|
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
|
|
|
|
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
|
|
|
|
|
|
|
|
mOpenGLESWindow = glfwCreateWindow(400, 400, "Dawn OpenGLES test window", nullptr, nullptr);
|
|
|
|
|
|
|
|
glfwMakeContextCurrent(mOpenGLESWindow);
|
|
|
|
dawn_native::opengl::AdapterDiscoveryOptionsES adapterOptionsES;
|
|
|
|
adapterOptionsES.getProc = adapterOptions.getProc;
|
|
|
|
instance->DiscoverAdapters(&adapterOptionsES);
|
2020-05-15 16:04:32 +00:00
|
|
|
#endif // DAWN_ENABLE_BACKEND_OPENGL
|
|
|
|
|
|
|
|
return instance;
|
2019-08-28 23:18:10 +00:00
|
|
|
}
|
|
|
|
|
2020-11-25 16:45:04 +00:00
|
|
|
GLFWwindow* DawnTestEnvironment::GetOpenGLWindow() const {
|
|
|
|
return mOpenGLWindow;
|
|
|
|
}
|
|
|
|
|
|
|
|
GLFWwindow* DawnTestEnvironment::GetOpenGLESWindow() const {
|
|
|
|
return mOpenGLESWindow;
|
|
|
|
}
|
|
|
|
|
2020-05-15 20:28:05 +00:00
|
|
|
void DawnTestEnvironment::SelectPreferredAdapterProperties(const dawn_native::Instance* instance) {
|
|
|
|
// Get the first available preferred device type.
|
|
|
|
dawn_native::DeviceType preferredDeviceType = static_cast<dawn_native::DeviceType>(-1);
|
|
|
|
bool hasDevicePreference = false;
|
|
|
|
for (dawn_native::DeviceType devicePreference : mDevicePreferences) {
|
|
|
|
for (const dawn_native::Adapter& adapter : instance->GetAdapters()) {
|
|
|
|
wgpu::AdapterProperties properties;
|
|
|
|
adapter.GetProperties(&properties);
|
|
|
|
|
|
|
|
if (adapter.GetDeviceType() == devicePreference) {
|
|
|
|
preferredDeviceType = devicePreference;
|
|
|
|
hasDevicePreference = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (hasDevicePreference) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-05 08:38:46 +00:00
|
|
|
std::set<std::pair<wgpu::BackendType, std::string>> adapterNameSet;
|
2020-05-15 16:07:12 +00:00
|
|
|
for (const dawn_native::Adapter& adapter : instance->GetAdapters()) {
|
|
|
|
wgpu::AdapterProperties properties;
|
|
|
|
adapter.GetProperties(&properties);
|
|
|
|
|
2020-05-15 20:28:05 +00:00
|
|
|
// The adapter is selected if:
|
|
|
|
bool selected = false;
|
|
|
|
if (mHasVendorIdFilter) {
|
|
|
|
// It matches the vendor id, if present.
|
|
|
|
selected = mVendorIdFilter == properties.vendorID;
|
|
|
|
|
|
|
|
if (!mDevicePreferences.empty()) {
|
|
|
|
dawn::WarningLog() << "Vendor ID filter provided. Ignoring device type preference.";
|
|
|
|
}
|
|
|
|
} else if (hasDevicePreference) {
|
|
|
|
// There is a device preference and:
|
|
|
|
selected =
|
|
|
|
// The device type matches the first available preferred type for that backend, if
|
|
|
|
// present.
|
|
|
|
(adapter.GetDeviceType() == preferredDeviceType) ||
|
|
|
|
// Always select Unknown OpenGL adapters if we don't want a CPU adapter.
|
|
|
|
// OpenGL will usually be unknown because we can't query the device type.
|
|
|
|
// If we ever have Swiftshader GL (unlikely), we could set the DeviceType properly.
|
|
|
|
(preferredDeviceType != dawn_native::DeviceType::CPU &&
|
|
|
|
adapter.GetDeviceType() == dawn_native::DeviceType::Unknown &&
|
|
|
|
properties.backendType == wgpu::BackendType::OpenGL) ||
|
|
|
|
// Always select the Null backend. There are few tests on this backend, and they run
|
|
|
|
// quickly. This is temporary as to not lose coverage. We can group it with
|
|
|
|
// Swiftshader as a CPU adapter when we have Swiftshader tests.
|
|
|
|
(properties.backendType == wgpu::BackendType::Null);
|
|
|
|
} else {
|
|
|
|
// No vendor id or device preference was provided (select all).
|
|
|
|
selected = true;
|
|
|
|
}
|
|
|
|
|
2020-11-05 08:38:46 +00:00
|
|
|
// In Windows Remote Desktop sessions we may be able to discover multiple adapters that
|
|
|
|
// have the same name and backend type. We will just choose one adapter from them in our
|
|
|
|
// tests.
|
|
|
|
const auto adapterTypeAndName =
|
|
|
|
std::make_pair(properties.backendType, std::string(properties.name));
|
|
|
|
if (adapterNameSet.find(adapterTypeAndName) == adapterNameSet.end()) {
|
|
|
|
adapterNameSet.insert(adapterTypeAndName);
|
|
|
|
mAdapterProperties.emplace_back(properties, selected);
|
|
|
|
}
|
2020-05-15 16:07:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-15 20:28:05 +00:00
|
|
|
std::vector<AdapterTestParam> DawnTestEnvironment::GetAvailableAdapterTestParamsForBackends(
|
|
|
|
const BackendTestConfig* params,
|
|
|
|
size_t numParams) {
|
|
|
|
std::vector<AdapterTestParam> testParams;
|
2020-05-15 16:07:12 +00:00
|
|
|
for (size_t i = 0; i < numParams; ++i) {
|
|
|
|
for (const auto& adapterProperties : mAdapterProperties) {
|
2020-05-15 20:28:05 +00:00
|
|
|
if (params[i].backendType == adapterProperties.backendType &&
|
|
|
|
adapterProperties.selected) {
|
|
|
|
testParams.push_back(AdapterTestParam(params[i], adapterProperties));
|
2020-12-08 16:49:34 +00:00
|
|
|
|
|
|
|
// HACK: This is a hack to get Tint generator enabled on all tests
|
|
|
|
// without adding a new test suite in Chromium's infra config but skipping
|
|
|
|
// that suite on all unsupported platforms. Once we have basic functionality and
|
|
|
|
// test skips on all backends, we can remove this and use a test suite with
|
|
|
|
// use_tint_generator in the command line args instead.
|
|
|
|
if (params[i].backendType == wgpu::BackendType::Vulkan ||
|
|
|
|
params[i].backendType == wgpu::BackendType::OpenGL ||
|
|
|
|
params[i].backendType == wgpu::BackendType::OpenGLES) {
|
|
|
|
BackendTestConfig configWithTint = params[i];
|
|
|
|
configWithTint.forceEnabledWorkarounds.push_back("use_tint_generator");
|
|
|
|
testParams.push_back(AdapterTestParam(configWithTint, adapterProperties));
|
|
|
|
}
|
2020-05-15 16:07:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-05-15 20:28:05 +00:00
|
|
|
return testParams;
|
2020-05-15 16:07:12 +00:00
|
|
|
}
|
|
|
|
|
2020-11-14 01:09:23 +00:00
|
|
|
void DawnTestEnvironment::PrintTestConfigurationAndAdapterInfo(
|
|
|
|
dawn_native::Instance* instance) const {
|
2020-05-15 16:04:32 +00:00
|
|
|
dawn::LogMessage log = dawn::InfoLog();
|
|
|
|
log << "Testing configuration\n"
|
|
|
|
"---------------------\n"
|
|
|
|
"UseWire: "
|
|
|
|
<< (mUseWire ? "true" : "false")
|
|
|
|
<< "\n"
|
|
|
|
"EnableBackendValidation: "
|
2020-11-14 01:09:23 +00:00
|
|
|
<< (mEnableBackendValidation ? "true" : "false");
|
|
|
|
|
|
|
|
if (GetEnabledToggles().size() > 0) {
|
|
|
|
log << "\n"
|
|
|
|
"Enabled Toggles\n";
|
|
|
|
for (const std::string& toggle : GetEnabledToggles()) {
|
|
|
|
const dawn_native::ToggleInfo* info = instance->GetToggleInfo(toggle.c_str());
|
|
|
|
ASSERT(info != nullptr);
|
|
|
|
log << " - " << info->name << ": " << info->description << "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GetDisabledToggles().size() > 0) {
|
|
|
|
log << "\n"
|
|
|
|
"Disabled Toggles\n";
|
|
|
|
for (const std::string& toggle : GetDisabledToggles()) {
|
|
|
|
const dawn_native::ToggleInfo* info = instance->GetToggleInfo(toggle.c_str());
|
|
|
|
ASSERT(info != nullptr);
|
|
|
|
log << " - " << info->name << ": " << info->description << "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
log << "\n"
|
2020-05-15 16:04:32 +00:00
|
|
|
"BeginCaptureOnStartup: "
|
|
|
|
<< (mBeginCaptureOnStartup ? "true" : "false")
|
|
|
|
<< "\n"
|
|
|
|
"\n"
|
|
|
|
<< "System adapters: \n";
|
|
|
|
|
2020-05-15 16:07:12 +00:00
|
|
|
for (const TestAdapterProperties& properties : mAdapterProperties) {
|
2019-02-21 17:36:11 +00:00
|
|
|
std::ostringstream vendorId;
|
|
|
|
std::ostringstream deviceId;
|
|
|
|
vendorId << std::setfill('0') << std::uppercase << std::internal << std::hex << std::setw(4)
|
2020-01-10 13:28:18 +00:00
|
|
|
<< properties.vendorID;
|
2019-02-21 17:36:11 +00:00
|
|
|
deviceId << std::setfill('0') << std::uppercase << std::internal << std::hex << std::setw(4)
|
2020-01-10 13:28:18 +00:00
|
|
|
<< properties.deviceID;
|
2019-02-21 17:36:11 +00:00
|
|
|
|
2019-12-05 11:13:01 +00:00
|
|
|
// Preparing for outputting hex numbers
|
2020-05-15 16:04:32 +00:00
|
|
|
log << std::showbase << std::hex << std::setfill('0') << std::setw(4)
|
|
|
|
|
2020-10-14 13:33:15 +00:00
|
|
|
<< " - \"" << properties.adapterName << "\" - \"" << properties.driverDescription
|
|
|
|
<< "\"\n"
|
2020-05-15 16:04:32 +00:00
|
|
|
<< " type: " << AdapterTypeName(properties.adapterType)
|
|
|
|
<< ", backend: " << ParamName(properties.backendType) << "\n"
|
|
|
|
<< " vendorId: 0x" << vendorId.str() << ", deviceId: 0x" << deviceId.str()
|
2020-05-15 16:07:12 +00:00
|
|
|
<< (properties.selected ? " [Selected]" : "") << "\n";
|
2019-02-21 17:36:11 +00:00
|
|
|
}
|
2019-02-21 16:29:12 +00:00
|
|
|
}
|
|
|
|
|
2020-05-15 16:04:32 +00:00
|
|
|
void DawnTestEnvironment::SetUp() {
|
|
|
|
mInstance = CreateInstanceAndDiscoverAdapters();
|
|
|
|
ASSERT(mInstance);
|
|
|
|
}
|
|
|
|
|
2019-11-20 09:45:41 +00:00
|
|
|
void DawnTestEnvironment::TearDown() {
|
|
|
|
// When Vulkan validation layers are enabled, it's unsafe to call Vulkan APIs in the destructor
|
|
|
|
// of a static/global variable, so the instance must be manually released beforehand.
|
|
|
|
mInstance.reset();
|
|
|
|
}
|
|
|
|
|
2019-05-01 12:57:27 +00:00
|
|
|
bool DawnTestEnvironment::UsesWire() const {
|
2019-02-21 16:29:12 +00:00
|
|
|
return mUseWire;
|
|
|
|
}
|
|
|
|
|
2019-06-25 00:49:56 +00:00
|
|
|
bool DawnTestEnvironment::IsBackendValidationEnabled() const {
|
|
|
|
return mEnableBackendValidation;
|
|
|
|
}
|
|
|
|
|
2019-02-21 16:29:12 +00:00
|
|
|
dawn_native::Instance* DawnTestEnvironment::GetInstance() const {
|
|
|
|
return mInstance.get();
|
|
|
|
}
|
|
|
|
|
2019-07-08 03:25:54 +00:00
|
|
|
bool DawnTestEnvironment::HasVendorIdFilter() const {
|
|
|
|
return mHasVendorIdFilter;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t DawnTestEnvironment::GetVendorIdFilter() const {
|
|
|
|
return mVendorIdFilter;
|
|
|
|
}
|
|
|
|
|
2019-12-10 23:32:48 +00:00
|
|
|
const char* DawnTestEnvironment::GetWireTraceDir() const {
|
|
|
|
if (mWireTraceDir.length() == 0) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return mWireTraceDir.c_str();
|
|
|
|
}
|
|
|
|
|
2020-11-14 01:09:23 +00:00
|
|
|
const std::vector<std::string>& DawnTestEnvironment::GetEnabledToggles() const {
|
|
|
|
return mEnabledToggles;
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::vector<std::string>& DawnTestEnvironment::GetDisabledToggles() const {
|
|
|
|
return mDisabledToggles;
|
|
|
|
}
|
|
|
|
|
2019-12-10 23:32:48 +00:00
|
|
|
class WireServerTraceLayer : public dawn_wire::CommandHandler {
|
|
|
|
public:
|
2019-12-18 00:35:36 +00:00
|
|
|
WireServerTraceLayer(const char* file, dawn_wire::CommandHandler* handler)
|
|
|
|
: dawn_wire::CommandHandler(), mHandler(handler) {
|
|
|
|
mFile.open(file, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
|
2019-12-10 23:32:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const volatile char* HandleCommands(const volatile char* commands, size_t size) override {
|
|
|
|
mFile.write(const_cast<const char*>(commands), size);
|
2019-12-18 00:35:36 +00:00
|
|
|
return mHandler->HandleCommands(commands, size);
|
2019-12-10 23:32:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2019-12-18 00:35:36 +00:00
|
|
|
dawn_wire::CommandHandler* mHandler;
|
2019-12-10 23:32:48 +00:00
|
|
|
std::ofstream mFile;
|
|
|
|
};
|
|
|
|
|
2019-02-21 16:29:12 +00:00
|
|
|
// Implementation of DawnTest
|
|
|
|
|
2020-05-15 20:28:05 +00:00
|
|
|
DawnTestBase::DawnTestBase(const AdapterTestParam& param) : mParam(param) {
|
2019-08-28 23:18:10 +00:00
|
|
|
}
|
2018-09-06 13:26:48 +00:00
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
DawnTestBase::~DawnTestBase() {
|
2017-06-16 22:34:35 +00:00
|
|
|
// We need to destroy child objects before the Device
|
2017-11-23 19:51:16 +00:00
|
|
|
mReadbackSlots.clear();
|
2019-10-28 13:27:36 +00:00
|
|
|
queue = wgpu::Queue();
|
|
|
|
device = wgpu::Device();
|
2017-06-16 22:34:35 +00:00
|
|
|
|
2019-05-24 22:31:36 +00:00
|
|
|
mWireClient = nullptr;
|
|
|
|
mWireServer = nullptr;
|
|
|
|
if (gTestEnv->UsesWire()) {
|
|
|
|
backendProcs.deviceRelease(backendDevice);
|
|
|
|
}
|
|
|
|
|
2019-10-15 11:44:38 +00:00
|
|
|
dawnProcSetProcs(nullptr);
|
2017-06-16 22:34:35 +00:00
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
bool DawnTestBase::IsD3D12() const {
|
2020-05-15 20:28:05 +00:00
|
|
|
return mParam.adapterProperties.backendType == wgpu::BackendType::D3D12;
|
2017-07-13 00:36:36 +00:00
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
bool DawnTestBase::IsMetal() const {
|
2020-05-15 20:28:05 +00:00
|
|
|
return mParam.adapterProperties.backendType == wgpu::BackendType::Metal;
|
2017-07-18 14:31:50 +00:00
|
|
|
}
|
|
|
|
|
2020-03-20 17:07:20 +00:00
|
|
|
bool DawnTestBase::IsNull() const {
|
2020-05-15 20:28:05 +00:00
|
|
|
return mParam.adapterProperties.backendType == wgpu::BackendType::Null;
|
2020-03-20 17:07:20 +00:00
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
bool DawnTestBase::IsOpenGL() const {
|
2020-05-15 20:28:05 +00:00
|
|
|
return mParam.adapterProperties.backendType == wgpu::BackendType::OpenGL;
|
2017-07-18 14:31:50 +00:00
|
|
|
}
|
|
|
|
|
2020-11-25 16:45:04 +00:00
|
|
|
bool DawnTestBase::IsOpenGLES() const {
|
|
|
|
return mParam.adapterProperties.backendType == wgpu::BackendType::OpenGLES;
|
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
bool DawnTestBase::IsVulkan() const {
|
2020-05-15 20:28:05 +00:00
|
|
|
return mParam.adapterProperties.backendType == wgpu::BackendType::Vulkan;
|
2017-07-18 14:31:50 +00:00
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
bool DawnTestBase::IsAMD() const {
|
2020-05-15 20:28:05 +00:00
|
|
|
return gpu_info::IsAMD(mParam.adapterProperties.vendorID);
|
2018-09-19 00:32:52 +00:00
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
bool DawnTestBase::IsARM() const {
|
2020-05-15 20:28:05 +00:00
|
|
|
return gpu_info::IsARM(mParam.adapterProperties.vendorID);
|
2018-09-19 00:32:52 +00:00
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
bool DawnTestBase::IsImgTec() const {
|
2020-05-15 20:28:05 +00:00
|
|
|
return gpu_info::IsImgTec(mParam.adapterProperties.vendorID);
|
2018-09-19 00:32:52 +00:00
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
bool DawnTestBase::IsIntel() const {
|
2020-05-15 20:28:05 +00:00
|
|
|
return gpu_info::IsIntel(mParam.adapterProperties.vendorID);
|
2018-09-19 00:32:52 +00:00
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
bool DawnTestBase::IsNvidia() const {
|
2020-05-15 20:28:05 +00:00
|
|
|
return gpu_info::IsNvidia(mParam.adapterProperties.vendorID);
|
2018-09-19 00:32:52 +00:00
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
bool DawnTestBase::IsQualcomm() const {
|
2020-05-15 20:28:05 +00:00
|
|
|
return gpu_info::IsQualcomm(mParam.adapterProperties.vendorID);
|
2018-09-19 00:32:52 +00:00
|
|
|
}
|
|
|
|
|
2020-04-09 08:16:30 +00:00
|
|
|
bool DawnTestBase::IsSwiftshader() const {
|
2020-05-15 20:28:05 +00:00
|
|
|
return gpu_info::IsSwiftshader(mParam.adapterProperties.vendorID,
|
|
|
|
mParam.adapterProperties.deviceID);
|
2020-04-09 08:16:30 +00:00
|
|
|
}
|
|
|
|
|
2020-07-10 22:58:48 +00:00
|
|
|
bool DawnTestBase::IsWARP() const {
|
|
|
|
return gpu_info::IsWARP(mParam.adapterProperties.vendorID, mParam.adapterProperties.deviceID);
|
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
bool DawnTestBase::IsWindows() const {
|
2018-09-19 00:32:52 +00:00
|
|
|
#ifdef DAWN_PLATFORM_WINDOWS
|
|
|
|
return true;
|
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
bool DawnTestBase::IsLinux() const {
|
2018-09-19 00:32:52 +00:00
|
|
|
#ifdef DAWN_PLATFORM_LINUX
|
|
|
|
return true;
|
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
bool DawnTestBase::IsMacOS() const {
|
2018-09-19 00:32:52 +00:00
|
|
|
#ifdef DAWN_PLATFORM_APPLE
|
|
|
|
return true;
|
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
bool DawnTestBase::UsesWire() const {
|
2019-05-01 12:57:27 +00:00
|
|
|
return gTestEnv->UsesWire();
|
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
bool DawnTestBase::IsBackendValidationEnabled() const {
|
2019-06-25 00:49:56 +00:00
|
|
|
return gTestEnv->IsBackendValidationEnabled();
|
|
|
|
}
|
|
|
|
|
2020-09-09 23:11:57 +00:00
|
|
|
bool DawnTestBase::HasWGSL() const {
|
|
|
|
#ifdef DAWN_ENABLE_WGSL
|
|
|
|
return true;
|
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2020-06-19 17:35:33 +00:00
|
|
|
bool DawnTestBase::IsAsan() const {
|
|
|
|
#if defined(ADDRESS_SANITIZER)
|
|
|
|
return true;
|
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2020-11-05 18:52:49 +00:00
|
|
|
bool DawnTestBase::HasToggleEnabled(const char* toggle) const {
|
2020-12-04 02:07:20 +00:00
|
|
|
auto toggles = dawn_native::GetTogglesUsed(backendDevice);
|
2020-11-14 01:09:23 +00:00
|
|
|
return std::find_if(toggles.begin(), toggles.end(), [toggle](const char* name) {
|
|
|
|
return strcmp(toggle, name) == 0;
|
|
|
|
}) != toggles.end();
|
2020-11-05 18:52:49 +00:00
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
bool DawnTestBase::HasVendorIdFilter() const {
|
2019-07-08 03:25:54 +00:00
|
|
|
return gTestEnv->HasVendorIdFilter();
|
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
uint32_t DawnTestBase::GetVendorIdFilter() const {
|
2019-07-08 03:25:54 +00:00
|
|
|
return gTestEnv->GetVendorIdFilter();
|
|
|
|
}
|
|
|
|
|
2020-03-20 17:07:20 +00:00
|
|
|
wgpu::Instance DawnTestBase::GetInstance() const {
|
|
|
|
return gTestEnv->GetInstance()->Get();
|
|
|
|
}
|
|
|
|
|
|
|
|
dawn_native::Adapter DawnTestBase::GetAdapter() const {
|
|
|
|
return mBackendAdapter;
|
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
std::vector<const char*> DawnTestBase::GetRequiredExtensions() {
|
2019-08-02 00:06:38 +00:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2020-01-10 13:28:18 +00:00
|
|
|
const wgpu::AdapterProperties& DawnTestBase::GetAdapterProperties() const {
|
2020-05-15 20:28:05 +00:00
|
|
|
return mParam.adapterProperties;
|
2020-01-10 13:28:18 +00:00
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
bool DawnTestBase::SupportsExtensions(const std::vector<const char*>& extensions) {
|
2019-08-02 00:06:38 +00:00
|
|
|
ASSERT(mBackendAdapter);
|
|
|
|
std::set<std::string> supportedExtensionsSet;
|
|
|
|
for (const char* supportedExtensionName : mBackendAdapter.GetSupportedExtensions()) {
|
|
|
|
supportedExtensionsSet.insert(supportedExtensionName);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const char* extensionName : extensions) {
|
|
|
|
if (supportedExtensionsSet.find(extensionName) == supportedExtensionsSet.end()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
void DawnTestBase::SetUp() {
|
2019-02-12 15:48:15 +00:00
|
|
|
{
|
2020-05-15 20:28:05 +00:00
|
|
|
// Find the adapter that exactly matches our adapter properties.
|
|
|
|
const auto& adapters = gTestEnv->GetInstance()->GetAdapters();
|
|
|
|
const auto& it = std::find_if(
|
|
|
|
adapters.begin(), adapters.end(), [&](const dawn_native::Adapter& adapter) {
|
|
|
|
wgpu::AdapterProperties properties;
|
|
|
|
adapter.GetProperties(&properties);
|
|
|
|
|
|
|
|
return (mParam.adapterProperties.selected &&
|
|
|
|
properties.deviceID == mParam.adapterProperties.deviceID &&
|
|
|
|
properties.vendorID == mParam.adapterProperties.vendorID &&
|
|
|
|
properties.adapterType == mParam.adapterProperties.adapterType &&
|
|
|
|
properties.backendType == mParam.adapterProperties.backendType &&
|
|
|
|
strcmp(properties.name, mParam.adapterProperties.adapterName.c_str()) == 0);
|
|
|
|
});
|
|
|
|
ASSERT(it != adapters.end());
|
|
|
|
mBackendAdapter = *it;
|
2019-02-12 15:48:15 +00:00
|
|
|
}
|
2017-06-16 22:34:35 +00:00
|
|
|
|
2020-11-20 20:38:37 +00:00
|
|
|
// Setup the per-test platform. Tests can provide one by overloading CreateTestPlatform.
|
|
|
|
mTestPlatform = CreateTestPlatform();
|
|
|
|
gTestEnv->GetInstance()->SetPlatform(mTestPlatform.get());
|
|
|
|
|
2020-05-15 20:28:05 +00:00
|
|
|
// Create the device from the adapter
|
2019-08-28 23:18:10 +00:00
|
|
|
for (const char* forceEnabledWorkaround : mParam.forceEnabledWorkarounds) {
|
2019-05-11 00:21:50 +00:00
|
|
|
ASSERT(gTestEnv->GetInstance()->GetToggleInfo(forceEnabledWorkaround) != nullptr);
|
2019-04-26 07:52:57 +00:00
|
|
|
}
|
2019-08-28 23:18:10 +00:00
|
|
|
for (const char* forceDisabledWorkaround : mParam.forceDisabledWorkarounds) {
|
2019-06-11 18:11:05 +00:00
|
|
|
ASSERT(gTestEnv->GetInstance()->GetToggleInfo(forceDisabledWorkaround) != nullptr);
|
|
|
|
}
|
2019-05-29 00:07:37 +00:00
|
|
|
dawn_native::DeviceDescriptor deviceDescriptor;
|
2019-08-28 23:18:10 +00:00
|
|
|
deviceDescriptor.forceEnabledToggles = mParam.forceEnabledWorkarounds;
|
|
|
|
deviceDescriptor.forceDisabledToggles = mParam.forceDisabledWorkarounds;
|
2019-08-02 00:06:38 +00:00
|
|
|
deviceDescriptor.requiredExtensions = GetRequiredExtensions();
|
2019-11-21 00:48:39 +00:00
|
|
|
|
2020-11-14 01:09:23 +00:00
|
|
|
for (const std::string& toggle : gTestEnv->GetEnabledToggles()) {
|
|
|
|
const dawn_native::ToggleInfo* info =
|
|
|
|
gTestEnv->GetInstance()->GetToggleInfo(toggle.c_str());
|
|
|
|
ASSERT(info != nullptr);
|
|
|
|
deviceDescriptor.forceEnabledToggles.push_back(info->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const std::string& toggle : gTestEnv->GetDisabledToggles()) {
|
|
|
|
const dawn_native::ToggleInfo* info =
|
|
|
|
gTestEnv->GetInstance()->GetToggleInfo(toggle.c_str());
|
|
|
|
ASSERT(info != nullptr);
|
|
|
|
deviceDescriptor.forceDisabledToggles.push_back(info->name);
|
2019-11-21 00:48:39 +00:00
|
|
|
}
|
|
|
|
|
2019-08-02 00:06:38 +00:00
|
|
|
backendDevice = mBackendAdapter.CreateDevice(&deviceDescriptor);
|
|
|
|
ASSERT_NE(nullptr, backendDevice);
|
2019-04-26 07:52:57 +00:00
|
|
|
|
2019-05-24 22:31:36 +00:00
|
|
|
backendProcs = dawn_native::GetProcs();
|
2017-06-16 22:34:35 +00:00
|
|
|
|
2018-06-07 11:10:44 +00:00
|
|
|
// Choose whether to use the backend procs and devices directly, or set up the wire.
|
2019-10-28 13:27:36 +00:00
|
|
|
WGPUDevice cDevice = nullptr;
|
2019-03-11 16:52:42 +00:00
|
|
|
DawnProcTable procs;
|
2018-06-07 11:10:44 +00:00
|
|
|
|
2019-05-01 12:57:27 +00:00
|
|
|
if (gTestEnv->UsesWire()) {
|
2018-09-06 13:26:48 +00:00
|
|
|
mC2sBuf = std::make_unique<utils::TerribleCommandBuffer>();
|
|
|
|
mS2cBuf = std::make_unique<utils::TerribleCommandBuffer>();
|
2018-06-07 11:10:44 +00:00
|
|
|
|
2019-07-19 16:01:48 +00:00
|
|
|
dawn_wire::WireServerDescriptor serverDesc = {};
|
|
|
|
serverDesc.device = backendDevice;
|
|
|
|
serverDesc.procs = &backendProcs;
|
|
|
|
serverDesc.serializer = mS2cBuf.get();
|
|
|
|
|
|
|
|
mWireServer.reset(new dawn_wire::WireServer(serverDesc));
|
2018-09-06 13:26:48 +00:00
|
|
|
mC2sBuf->SetHandler(mWireServer.get());
|
2018-06-07 11:10:44 +00:00
|
|
|
|
2019-12-10 23:32:48 +00:00
|
|
|
if (gTestEnv->GetWireTraceDir() != nullptr) {
|
|
|
|
std::string file =
|
|
|
|
std::string(
|
|
|
|
::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name()) +
|
|
|
|
"_" + ::testing::UnitTest::GetInstance()->current_test_info()->name();
|
|
|
|
// Replace slashes in gtest names with underscores so everything is in one directory.
|
|
|
|
std::replace(file.begin(), file.end(), '/', '_');
|
|
|
|
|
|
|
|
std::string fullPath = gTestEnv->GetWireTraceDir() + file;
|
|
|
|
|
|
|
|
mWireServerTraceLayer.reset(
|
|
|
|
new WireServerTraceLayer(fullPath.c_str(), mWireServer.get()));
|
|
|
|
mC2sBuf->SetHandler(mWireServerTraceLayer.get());
|
|
|
|
}
|
|
|
|
|
2019-07-19 16:01:48 +00:00
|
|
|
dawn_wire::WireClientDescriptor clientDesc = {};
|
|
|
|
clientDesc.serializer = mC2sBuf.get();
|
|
|
|
|
|
|
|
mWireClient.reset(new dawn_wire::WireClient(clientDesc));
|
2020-10-06 16:13:42 +00:00
|
|
|
cDevice = mWireClient->GetDevice();
|
|
|
|
procs = dawn_wire::client::GetProcs();
|
2018-09-06 13:26:48 +00:00
|
|
|
mS2cBuf->SetHandler(mWireClient.get());
|
2018-06-07 11:10:44 +00:00
|
|
|
} else {
|
|
|
|
procs = backendProcs;
|
|
|
|
cDevice = backendDevice;
|
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
// Set up the device and queue because all tests need them, and DawnTestBase needs them too for
|
|
|
|
// the deferred expectations.
|
2019-10-15 11:44:38 +00:00
|
|
|
dawnProcSetProcs(&procs);
|
2019-10-28 13:27:36 +00:00
|
|
|
device = wgpu::Device::Acquire(cDevice);
|
2020-04-17 16:45:17 +00:00
|
|
|
queue = device.GetDefaultQueue();
|
2017-06-16 22:34:35 +00:00
|
|
|
|
2019-08-27 21:43:56 +00:00
|
|
|
device.SetUncapturedErrorCallback(OnDeviceError, this);
|
2020-01-15 19:02:13 +00:00
|
|
|
device.SetDeviceLostCallback(OnDeviceLost, this);
|
2020-11-25 16:45:04 +00:00
|
|
|
#if defined(DAWN_ENABLE_BACKEND_OPENGL)
|
|
|
|
if (IsOpenGL()) {
|
|
|
|
glfwMakeContextCurrent(gTestEnv->GetOpenGLWindow());
|
|
|
|
} else if (IsOpenGLES()) {
|
|
|
|
glfwMakeContextCurrent(gTestEnv->GetOpenGLESWindow());
|
|
|
|
}
|
|
|
|
#endif
|
2020-12-03 11:21:57 +00:00
|
|
|
|
|
|
|
// A very large number of tests hang on Intel D3D12 with the debug adapter after a driver
|
|
|
|
// upgrade. Violently suppress this whole configuration until we figure out what to do.
|
|
|
|
// See https://crbug.com/dawn/598
|
|
|
|
DAWN_SKIP_TEST_IF(IsBackendValidationEnabled() && IsIntel() && IsD3D12());
|
|
|
|
|
2017-06-16 22:34:35 +00:00
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
void DawnTestBase::TearDown() {
|
2018-06-07 11:10:44 +00:00
|
|
|
FlushWire();
|
|
|
|
|
2017-06-16 22:34:35 +00:00
|
|
|
MapSlotsSynchronously();
|
|
|
|
ResolveExpectations();
|
|
|
|
|
2017-11-23 19:51:16 +00:00
|
|
|
for (size_t i = 0; i < mReadbackSlots.size(); ++i) {
|
|
|
|
mReadbackSlots[i].buffer.Unmap();
|
2017-07-25 15:29:28 +00:00
|
|
|
}
|
2020-10-28 21:23:45 +00:00
|
|
|
|
|
|
|
if (!UsesWire()) {
|
|
|
|
EXPECT_EQ(mLastWarningCount,
|
|
|
|
dawn_native::GetDeprecationWarningCountForTesting(device.Get()));
|
|
|
|
}
|
2017-06-16 22:34:35 +00:00
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
void DawnTestBase::StartExpectDeviceError() {
|
2019-02-28 09:45:48 +00:00
|
|
|
mExpectError = true;
|
|
|
|
mError = false;
|
|
|
|
}
|
2019-08-28 23:18:10 +00:00
|
|
|
bool DawnTestBase::EndExpectDeviceError() {
|
2019-02-28 09:45:48 +00:00
|
|
|
mExpectError = false;
|
|
|
|
return mError;
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
2019-10-28 13:27:36 +00:00
|
|
|
void DawnTestBase::OnDeviceError(WGPUErrorType type, const char* message, void* userdata) {
|
|
|
|
ASSERT(type != WGPUErrorType_NoError);
|
2019-08-28 23:18:10 +00:00
|
|
|
DawnTestBase* self = static_cast<DawnTestBase*>(userdata);
|
2019-02-28 09:45:48 +00:00
|
|
|
|
|
|
|
ASSERT_TRUE(self->mExpectError) << "Got unexpected device error: " << message;
|
|
|
|
ASSERT_FALSE(self->mError) << "Got two errors in expect block";
|
|
|
|
self->mError = true;
|
|
|
|
}
|
|
|
|
|
2020-01-15 19:02:13 +00:00
|
|
|
void DawnTestBase::OnDeviceLost(const char* message, void* userdata) {
|
2020-08-08 01:05:59 +00:00
|
|
|
// Using ADD_FAILURE + ASSERT instead of FAIL to prevent the current test from continuing with a
|
|
|
|
// corrupt state.
|
|
|
|
ADD_FAILURE() << "Device Lost during test: " << message;
|
|
|
|
ASSERT(false);
|
2020-01-15 19:02:13 +00:00
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
std::ostringstream& DawnTestBase::AddBufferExpectation(const char* file,
|
|
|
|
int line,
|
2019-10-28 13:27:36 +00:00
|
|
|
const wgpu::Buffer& buffer,
|
2019-08-28 23:18:10 +00:00
|
|
|
uint64_t offset,
|
|
|
|
uint64_t size,
|
|
|
|
detail::Expectation* expectation) {
|
2017-06-16 22:34:35 +00:00
|
|
|
auto readback = ReserveReadback(size);
|
|
|
|
|
|
|
|
// We need to enqueue the copy immediately because by the time we resolve the expectation,
|
|
|
|
// the buffer might have been modified.
|
2019-10-28 13:27:36 +00:00
|
|
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
2019-02-15 12:54:08 +00:00
|
|
|
encoder.CopyBufferToBuffer(buffer, offset, readback.buffer, readback.offset, size);
|
2017-06-16 22:34:35 +00:00
|
|
|
|
2019-10-28 13:27:36 +00:00
|
|
|
wgpu::CommandBuffer commands = encoder.Finish();
|
2017-06-16 22:34:35 +00:00
|
|
|
queue.Submit(1, &commands);
|
|
|
|
|
|
|
|
DeferredExpectation deferred;
|
|
|
|
deferred.file = file;
|
|
|
|
deferred.line = line;
|
|
|
|
deferred.readbackSlot = readback.slot;
|
|
|
|
deferred.readbackOffset = readback.offset;
|
|
|
|
deferred.size = size;
|
2017-07-13 19:10:30 +00:00
|
|
|
deferred.rowBytes = size;
|
2020-04-24 10:02:43 +00:00
|
|
|
deferred.bytesPerRow = size;
|
2018-09-06 13:26:48 +00:00
|
|
|
deferred.expectation.reset(expectation);
|
2017-06-16 22:34:35 +00:00
|
|
|
|
2017-11-23 19:51:16 +00:00
|
|
|
mDeferredExpectations.push_back(std::move(deferred));
|
|
|
|
mDeferredExpectations.back().message = std::make_unique<std::ostringstream>();
|
|
|
|
return *(mDeferredExpectations.back().message.get());
|
2017-06-16 22:34:35 +00:00
|
|
|
}
|
|
|
|
|
2020-08-04 19:46:37 +00:00
|
|
|
std::ostringstream& DawnTestBase::AddTextureExpectationImpl(const char* file,
|
|
|
|
int line,
|
|
|
|
detail::Expectation* expectation,
|
|
|
|
const wgpu::Texture& texture,
|
|
|
|
uint32_t x,
|
|
|
|
uint32_t y,
|
|
|
|
uint32_t width,
|
|
|
|
uint32_t height,
|
|
|
|
uint32_t level,
|
|
|
|
uint32_t slice,
|
|
|
|
wgpu::TextureAspect aspect,
|
|
|
|
uint32_t dataSize,
|
|
|
|
uint32_t bytesPerRow) {
|
|
|
|
if (bytesPerRow == 0) {
|
|
|
|
bytesPerRow = Align(width * dataSize, kTextureBytesPerRowAlignment);
|
|
|
|
} else {
|
|
|
|
ASSERT(bytesPerRow >= width * dataSize);
|
|
|
|
ASSERT(bytesPerRow == Align(bytesPerRow, kTextureBytesPerRowAlignment));
|
|
|
|
}
|
2017-06-27 04:11:16 +00:00
|
|
|
|
2020-10-23 21:21:33 +00:00
|
|
|
uint32_t rowsPerImage = height;
|
|
|
|
uint32_t depth = 1;
|
|
|
|
uint32_t size =
|
|
|
|
utils::RequiredBytesInCopy(bytesPerRow, rowsPerImage, width, height, depth, dataSize);
|
2020-08-04 19:46:37 +00:00
|
|
|
|
|
|
|
// TODO(enga): We should have the map async alignment in Contants.h. Also, it should change to 8
|
|
|
|
// for Float64Array.
|
|
|
|
auto readback = ReserveReadback(Align(size, 4));
|
2017-06-27 04:11:16 +00:00
|
|
|
|
|
|
|
// We need to enqueue the copy immediately because by the time we resolve the expectation,
|
|
|
|
// the texture might have been modified.
|
2019-10-28 13:27:36 +00:00
|
|
|
wgpu::TextureCopyView textureCopyView =
|
2020-08-04 19:46:37 +00:00
|
|
|
utils::CreateTextureCopyView(texture, level, {x, y, slice}, aspect);
|
2019-10-28 13:27:36 +00:00
|
|
|
wgpu::BufferCopyView bufferCopyView =
|
2020-11-06 13:41:50 +00:00
|
|
|
utils::CreateBufferCopyView(readback.buffer, readback.offset, bytesPerRow, rowsPerImage);
|
2019-10-28 13:27:36 +00:00
|
|
|
wgpu::Extent3D copySize = {width, height, 1};
|
2017-06-27 04:11:16 +00:00
|
|
|
|
2019-10-28 13:27:36 +00:00
|
|
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
2019-02-15 12:54:08 +00:00
|
|
|
encoder.CopyTextureToBuffer(&textureCopyView, &bufferCopyView, ©Size);
|
|
|
|
|
2019-10-28 13:27:36 +00:00
|
|
|
wgpu::CommandBuffer commands = encoder.Finish();
|
2017-06-27 04:11:16 +00:00
|
|
|
queue.Submit(1, &commands);
|
|
|
|
|
|
|
|
DeferredExpectation deferred;
|
|
|
|
deferred.file = file;
|
|
|
|
deferred.line = line;
|
|
|
|
deferred.readbackSlot = readback.slot;
|
|
|
|
deferred.readbackOffset = readback.offset;
|
|
|
|
deferred.size = size;
|
2020-08-04 19:46:37 +00:00
|
|
|
deferred.rowBytes = width * dataSize;
|
2020-04-24 10:02:43 +00:00
|
|
|
deferred.bytesPerRow = bytesPerRow;
|
2018-09-06 13:26:48 +00:00
|
|
|
deferred.expectation.reset(expectation);
|
2017-06-27 04:11:16 +00:00
|
|
|
|
2017-11-23 19:51:16 +00:00
|
|
|
mDeferredExpectations.push_back(std::move(deferred));
|
|
|
|
mDeferredExpectations.back().message = std::make_unique<std::ostringstream>();
|
|
|
|
return *(mDeferredExpectations.back().message.get());
|
2017-06-27 04:11:16 +00:00
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
void DawnTestBase::WaitABit() {
|
2017-07-17 21:13:57 +00:00
|
|
|
device.Tick();
|
2018-06-07 11:10:44 +00:00
|
|
|
FlushWire();
|
|
|
|
|
2017-07-17 21:13:57 +00:00
|
|
|
utils::USleep(100);
|
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
void DawnTestBase::FlushWire() {
|
2019-05-01 12:57:27 +00:00
|
|
|
if (gTestEnv->UsesWire()) {
|
2019-02-11 23:34:52 +00:00
|
|
|
bool C2SFlushed = mC2sBuf->Flush();
|
|
|
|
bool S2CFlushed = mS2cBuf->Flush();
|
|
|
|
ASSERT(C2SFlushed);
|
|
|
|
ASSERT(S2CFlushed);
|
2018-06-07 11:10:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-12 22:32:33 +00:00
|
|
|
void DawnTestBase::WaitForAllOperations() {
|
|
|
|
wgpu::Queue queue = device.GetDefaultQueue();
|
|
|
|
wgpu::Fence fence = queue.CreateFence();
|
|
|
|
|
|
|
|
// Force the currently submitted operations to completed.
|
|
|
|
queue.Signal(fence, 1);
|
|
|
|
while (fence.GetCompletedValue() < 1) {
|
|
|
|
WaitABit();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
DawnTestBase::ReadbackReservation DawnTestBase::ReserveReadback(uint64_t readbackSize) {
|
2017-06-16 22:34:35 +00:00
|
|
|
// For now create a new MapRead buffer for each readback
|
|
|
|
// TODO(cwallez@chromium.org): eventually make bigger buffers and allocate linearly?
|
|
|
|
ReadbackSlot slot;
|
|
|
|
slot.bufferSize = readbackSize;
|
2020-08-23 06:08:05 +00:00
|
|
|
|
|
|
|
// Create and initialize the slot buffer so that it won't unexpectedly affect the count of
|
|
|
|
// resource lazy clear in the tests.
|
|
|
|
const std::vector<uint8_t> initialBufferData(readbackSize, 0u);
|
|
|
|
slot.buffer =
|
|
|
|
utils::CreateBufferFromData(device, initialBufferData.data(), readbackSize,
|
|
|
|
wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst);
|
2017-06-16 22:34:35 +00:00
|
|
|
|
|
|
|
ReadbackReservation reservation;
|
2018-10-25 10:42:49 +00:00
|
|
|
reservation.buffer = slot.buffer;
|
2017-11-23 19:51:16 +00:00
|
|
|
reservation.slot = mReadbackSlots.size();
|
2017-06-16 22:34:35 +00:00
|
|
|
reservation.offset = 0;
|
|
|
|
|
2017-11-23 19:51:16 +00:00
|
|
|
mReadbackSlots.push_back(std::move(slot));
|
2017-06-16 22:34:35 +00:00
|
|
|
return reservation;
|
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
void DawnTestBase::MapSlotsSynchronously() {
|
2018-07-18 13:18:25 +00:00
|
|
|
// Initialize numPendingMapOperations before mapping, just in case the callback is called
|
|
|
|
// immediately.
|
2017-11-23 19:51:16 +00:00
|
|
|
mNumPendingMapOperations = mReadbackSlots.size();
|
2017-06-16 22:34:35 +00:00
|
|
|
|
|
|
|
// Map all readback slots
|
2017-11-23 19:51:16 +00:00
|
|
|
for (size_t i = 0; i < mReadbackSlots.size(); ++i) {
|
2019-05-29 13:03:50 +00:00
|
|
|
MapReadUserdata* userdata = new MapReadUserdata{this, i};
|
2017-06-16 22:34:35 +00:00
|
|
|
|
2020-07-16 16:35:40 +00:00
|
|
|
const ReadbackSlot& slot = mReadbackSlots[i];
|
|
|
|
slot.buffer.MapAsync(wgpu::MapMode::Read, 0, 0, SlotMapCallback, userdata);
|
2017-06-16 22:34:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Busy wait until all map operations are done.
|
2017-11-23 19:51:16 +00:00
|
|
|
while (mNumPendingMapOperations != 0) {
|
2017-07-17 21:13:57 +00:00
|
|
|
WaitABit();
|
2017-06-16 22:34:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
2020-07-16 16:35:40 +00:00
|
|
|
void DawnTestBase::SlotMapCallback(WGPUBufferMapAsyncStatus status, void* userdata_) {
|
2019-10-28 13:27:36 +00:00
|
|
|
DAWN_ASSERT(status == WGPUBufferMapAsyncStatus_Success);
|
2017-06-16 22:34:35 +00:00
|
|
|
|
2020-07-16 16:35:40 +00:00
|
|
|
std::unique_ptr<MapReadUserdata> userdata(static_cast<MapReadUserdata*>(userdata_));
|
|
|
|
DawnTestBase* test = userdata->test;
|
|
|
|
ReadbackSlot* slot = &test->mReadbackSlots[userdata->slot];
|
2017-06-16 22:34:35 +00:00
|
|
|
|
2020-07-16 16:35:40 +00:00
|
|
|
slot->mappedData = slot->buffer.GetConstMappedRange();
|
|
|
|
test->mNumPendingMapOperations--;
|
2017-06-16 22:34:35 +00:00
|
|
|
}
|
|
|
|
|
2019-08-28 23:18:10 +00:00
|
|
|
void DawnTestBase::ResolveExpectations() {
|
2017-11-23 19:51:16 +00:00
|
|
|
for (const auto& expectation : mDeferredExpectations) {
|
2018-07-18 11:37:54 +00:00
|
|
|
DAWN_ASSERT(mReadbackSlots[expectation.readbackSlot].mappedData != nullptr);
|
2017-06-16 22:34:35 +00:00
|
|
|
|
|
|
|
// Get a pointer to the mapped copy of the data for the expectation.
|
2018-07-18 13:18:25 +00:00
|
|
|
const char* data =
|
2019-05-03 00:58:27 +00:00
|
|
|
static_cast<const char*>(mReadbackSlots[expectation.readbackSlot].mappedData);
|
2017-06-16 22:34:35 +00:00
|
|
|
data += expectation.readbackOffset;
|
|
|
|
|
2017-07-13 19:10:30 +00:00
|
|
|
uint32_t size;
|
|
|
|
std::vector<char> packedData;
|
2020-04-24 10:02:43 +00:00
|
|
|
if (expectation.rowBytes != expectation.bytesPerRow) {
|
|
|
|
DAWN_ASSERT(expectation.bytesPerRow > expectation.rowBytes);
|
2018-07-18 13:18:25 +00:00
|
|
|
uint32_t rowCount =
|
2020-04-24 10:02:43 +00:00
|
|
|
(expectation.size + expectation.bytesPerRow - 1) / expectation.bytesPerRow;
|
2017-07-13 19:10:30 +00:00
|
|
|
uint32_t packedSize = rowCount * expectation.rowBytes;
|
|
|
|
packedData.resize(packedSize);
|
|
|
|
for (uint32_t r = 0; r < rowCount; ++r) {
|
|
|
|
for (uint32_t i = 0; i < expectation.rowBytes; ++i) {
|
2020-04-24 10:02:43 +00:00
|
|
|
packedData[i + r * expectation.rowBytes] =
|
|
|
|
data[i + r * expectation.bytesPerRow];
|
2017-07-13 19:10:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
data = packedData.data();
|
|
|
|
size = packedSize;
|
|
|
|
} else {
|
|
|
|
size = expectation.size;
|
|
|
|
}
|
|
|
|
|
2017-06-16 22:34:35 +00:00
|
|
|
// Get the result for the expectation and add context to failures
|
2017-07-13 19:10:30 +00:00
|
|
|
testing::AssertionResult result = expectation.expectation->Check(data, size);
|
2017-06-16 22:34:35 +00:00
|
|
|
if (!result) {
|
2018-07-18 13:18:25 +00:00
|
|
|
result << " Expectation created at " << expectation.file << ":" << expectation.line
|
|
|
|
<< std::endl;
|
2017-07-17 13:37:08 +00:00
|
|
|
result << expectation.message->str();
|
2017-06-16 22:34:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
EXPECT_TRUE(result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-20 20:38:37 +00:00
|
|
|
std::unique_ptr<dawn_platform::Platform> DawnTestBase::CreateTestPlatform() {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-06-27 04:11:16 +00:00
|
|
|
bool RGBA8::operator==(const RGBA8& other) const {
|
|
|
|
return r == other.r && g == other.g && b == other.b && a == other.a;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool RGBA8::operator!=(const RGBA8& other) const {
|
|
|
|
return !(*this == other);
|
|
|
|
}
|
|
|
|
|
2020-12-24 03:11:17 +00:00
|
|
|
bool RGBA8::operator<=(const RGBA8& other) const {
|
|
|
|
return (r <= other.r && g <= other.g && b <= other.b && a <= other.a);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool RGBA8::operator>=(const RGBA8& other) const {
|
|
|
|
return (r >= other.r && g >= other.g && b >= other.b && a >= other.a);
|
|
|
|
}
|
|
|
|
|
2018-07-18 13:18:25 +00:00
|
|
|
std::ostream& operator<<(std::ostream& stream, const RGBA8& color) {
|
|
|
|
return stream << "RGBA8(" << static_cast<int>(color.r) << ", " << static_cast<int>(color.g)
|
|
|
|
<< ", " << static_cast<int>(color.b) << ", " << static_cast<int>(color.a) << ")";
|
2017-06-27 04:11:16 +00:00
|
|
|
}
|
|
|
|
|
2017-06-16 22:34:35 +00:00
|
|
|
namespace detail {
|
2020-05-15 20:28:05 +00:00
|
|
|
std::vector<AdapterTestParam> GetAvailableAdapterTestParamsForBackends(
|
|
|
|
const BackendTestConfig* params,
|
|
|
|
size_t numParams) {
|
2020-05-15 16:07:12 +00:00
|
|
|
ASSERT(gTestEnv != nullptr);
|
2020-05-15 20:28:05 +00:00
|
|
|
return gTestEnv->GetAvailableAdapterTestParamsForBackends(params, numParams);
|
2017-06-16 22:34:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Helper classes to set expectations
|
|
|
|
|
2018-07-18 13:18:25 +00:00
|
|
|
template <typename T>
|
2017-06-16 22:34:35 +00:00
|
|
|
ExpectEq<T>::ExpectEq(T singleValue) {
|
2017-11-23 19:51:16 +00:00
|
|
|
mExpected.push_back(singleValue);
|
2017-06-16 22:34:35 +00:00
|
|
|
}
|
|
|
|
|
2018-07-18 13:18:25 +00:00
|
|
|
template <typename T>
|
2017-07-04 14:53:42 +00:00
|
|
|
ExpectEq<T>::ExpectEq(const T* values, const unsigned int count) {
|
2017-11-23 19:51:16 +00:00
|
|
|
mExpected.assign(values, values + count);
|
2017-07-04 14:53:42 +00:00
|
|
|
}
|
|
|
|
|
2018-07-18 13:18:25 +00:00
|
|
|
template <typename T>
|
2017-06-16 22:34:35 +00:00
|
|
|
testing::AssertionResult ExpectEq<T>::Check(const void* data, size_t size) {
|
2018-07-18 11:37:54 +00:00
|
|
|
DAWN_ASSERT(size == sizeof(T) * mExpected.size());
|
2017-06-16 22:34:35 +00:00
|
|
|
|
2019-05-03 00:58:27 +00:00
|
|
|
const T* actual = static_cast<const T*>(data);
|
2017-07-17 13:37:46 +00:00
|
|
|
|
2017-11-23 19:51:16 +00:00
|
|
|
for (size_t i = 0; i < mExpected.size(); ++i) {
|
|
|
|
if (actual[i] != mExpected[i]) {
|
2018-07-18 13:18:25 +00:00
|
|
|
testing::AssertionResult result = testing::AssertionFailure()
|
|
|
|
<< "Expected data[" << i << "] to be "
|
|
|
|
<< mExpected[i] << ", actual " << actual[i]
|
|
|
|
<< std::endl;
|
2017-07-17 13:37:46 +00:00
|
|
|
|
2017-11-23 19:51:16 +00:00
|
|
|
if (mExpected.size() <= 1024) {
|
2017-07-17 13:37:46 +00:00
|
|
|
result << "Expected:" << std::endl;
|
2020-12-24 03:11:17 +00:00
|
|
|
printBuffer(result, mExpected.data(), mExpected.size());
|
2017-07-17 13:37:46 +00:00
|
|
|
|
|
|
|
result << "Actual:" << std::endl;
|
2020-12-24 03:11:17 +00:00
|
|
|
printBuffer(result, actual, mExpected.size());
|
2017-07-17 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
2017-06-16 22:34:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return testing::AssertionSuccess();
|
|
|
|
}
|
|
|
|
|
2018-02-04 16:07:02 +00:00
|
|
|
template class ExpectEq<uint8_t>;
|
2020-06-08 12:18:21 +00:00
|
|
|
template class ExpectEq<uint16_t>;
|
2017-06-16 22:34:35 +00:00
|
|
|
template class ExpectEq<uint32_t>;
|
2020-08-04 06:41:56 +00:00
|
|
|
template class ExpectEq<uint64_t>;
|
2017-06-27 04:11:16 +00:00
|
|
|
template class ExpectEq<RGBA8>;
|
2020-01-16 00:12:10 +00:00
|
|
|
template class ExpectEq<float>;
|
2020-12-24 03:11:17 +00:00
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
ExpectBetweenColors<T>::ExpectBetweenColors(T value0, T value1) {
|
|
|
|
T l, h;
|
|
|
|
l.r = std::min(value0.r, value1.r);
|
|
|
|
l.g = std::min(value0.g, value1.g);
|
|
|
|
l.b = std::min(value0.b, value1.b);
|
|
|
|
l.a = std::min(value0.a, value1.a);
|
|
|
|
|
|
|
|
h.r = std::max(value0.r, value1.r);
|
|
|
|
h.g = std::max(value0.g, value1.g);
|
|
|
|
h.b = std::max(value0.b, value1.b);
|
|
|
|
h.a = std::max(value0.a, value1.a);
|
|
|
|
|
|
|
|
mLowerColorChannels.push_back(l);
|
|
|
|
mHigherColorChannels.push_back(h);
|
|
|
|
|
|
|
|
mValues0.push_back(value0);
|
|
|
|
mValues1.push_back(value1);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
testing::AssertionResult ExpectBetweenColors<T>::Check(const void* data, size_t size) {
|
|
|
|
DAWN_ASSERT(size == sizeof(T) * mLowerColorChannels.size());
|
|
|
|
DAWN_ASSERT(mHigherColorChannels.size() == mLowerColorChannels.size());
|
|
|
|
DAWN_ASSERT(mValues0.size() == mValues1.size());
|
|
|
|
DAWN_ASSERT(mValues0.size() == mLowerColorChannels.size());
|
|
|
|
|
|
|
|
const T* actual = static_cast<const T*>(data);
|
|
|
|
|
|
|
|
for (size_t i = 0; i < mLowerColorChannels.size(); ++i) {
|
|
|
|
if (!(actual[i] >= mLowerColorChannels[i] && actual[i] <= mHigherColorChannels[i])) {
|
|
|
|
testing::AssertionResult result = testing::AssertionFailure()
|
|
|
|
<< "Expected data[" << i << "] to be between "
|
|
|
|
<< mValues0[i] << " and " << mValues1[i]
|
|
|
|
<< ", actual " << actual[i] << std::endl;
|
|
|
|
|
|
|
|
if (mLowerColorChannels.size() <= 1024) {
|
|
|
|
result << "Expected between:" << std::endl;
|
|
|
|
printBuffer(result, mValues0.data(), mLowerColorChannels.size());
|
|
|
|
result << "and" << std::endl;
|
|
|
|
printBuffer(result, mValues1.data(), mLowerColorChannels.size());
|
|
|
|
|
|
|
|
result << "Actual:" << std::endl;
|
|
|
|
printBuffer(result, actual, mLowerColorChannels.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return testing::AssertionSuccess();
|
|
|
|
}
|
|
|
|
|
|
|
|
template class ExpectBetweenColors<RGBA8>;
|
2018-07-18 13:18:25 +00:00
|
|
|
} // namespace detail
|