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"
|
2017-07-13 19:10:30 +00:00
|
|
|
#include "common/Constants.h"
|
|
|
|
#include "common/Math.h"
|
2018-09-19 00:32:52 +00:00
|
|
|
#include "common/Platform.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"
|
2017-06-16 22:34:35 +00:00
|
|
|
#include "utils/BackendBinding.h"
|
2018-07-18 12:00:56 +00:00
|
|
|
#include "utils/DawnHelpers.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"
|
2017-06-16 22:34:35 +00:00
|
|
|
|
2019-02-12 15:48:15 +00:00
|
|
|
#include <algorithm>
|
2019-02-21 17:36:11 +00:00
|
|
|
#include <iomanip>
|
2018-01-19 17:53:46 +00:00
|
|
|
#include <iostream>
|
2019-02-21 17:36:11 +00:00
|
|
|
#include <sstream>
|
2019-02-05 12:17:20 +00:00
|
|
|
#include <unordered_map>
|
2017-06-16 22:34:35 +00:00
|
|
|
#include "GLFW/glfw3.h"
|
2018-06-07 11:10:44 +00:00
|
|
|
|
2017-06-16 22:34:35 +00:00
|
|
|
namespace {
|
|
|
|
|
2019-02-05 12:17:20 +00:00
|
|
|
std::string ParamName(dawn_native::BackendType type) {
|
2018-07-18 13:18:25 +00:00
|
|
|
switch (type) {
|
2019-02-05 12:17:20 +00:00
|
|
|
case dawn_native::BackendType::D3D12:
|
2017-06-16 22:34:35 +00:00
|
|
|
return "D3D12";
|
2019-02-05 12:17:20 +00:00
|
|
|
case dawn_native::BackendType::Metal:
|
2017-06-16 22:34:35 +00:00
|
|
|
return "Metal";
|
2019-02-05 12:17:20 +00:00
|
|
|
case dawn_native::BackendType::Null:
|
|
|
|
return "Null";
|
|
|
|
case dawn_native::BackendType::OpenGL:
|
2017-06-16 22:34:35 +00:00
|
|
|
return "OpenGL";
|
2019-02-05 12:17:20 +00:00
|
|
|
case dawn_native::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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-15 16:36:25 +00:00
|
|
|
const char* DeviceTypeName(dawn_native::DeviceType type) {
|
|
|
|
switch (type) {
|
|
|
|
case dawn_native::DeviceType::DiscreteGPU:
|
|
|
|
return "Discrete GPU";
|
|
|
|
case dawn_native::DeviceType::IntegratedGPU:
|
|
|
|
return "Integrated GPU";
|
|
|
|
case dawn_native::DeviceType::CPU:
|
|
|
|
return "CPU";
|
|
|
|
case dawn_native::DeviceType::Unknown:
|
|
|
|
return "Unknown";
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-16 22:34:35 +00:00
|
|
|
struct MapReadUserdata {
|
2018-07-18 13:18:25 +00:00
|
|
|
DawnTest* 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;
|
|
|
|
|
2018-07-18 13:18:25 +00:00
|
|
|
} // namespace
|
2017-06-16 22:34:35 +00:00
|
|
|
|
2019-05-29 00:07:37 +00:00
|
|
|
const DawnTestParam D3D12Backend(dawn_native::BackendType::D3D12);
|
|
|
|
const DawnTestParam MetalBackend(dawn_native::BackendType::Metal);
|
|
|
|
const DawnTestParam OpenGLBackend(dawn_native::BackendType::OpenGL);
|
|
|
|
const DawnTestParam VulkanBackend(dawn_native::BackendType::Vulkan);
|
|
|
|
|
|
|
|
DawnTestParam ForceWorkarounds(const DawnTestParam& originParam,
|
2019-06-11 18:11:05 +00:00
|
|
|
std::initializer_list<const char*> forceEnabledWorkarounds,
|
|
|
|
std::initializer_list<const char*> forceDisabledWorkarounds) {
|
2019-04-26 07:52:57 +00:00
|
|
|
DawnTestParam newTestParam = originParam;
|
2019-05-29 00:07:37 +00:00
|
|
|
newTestParam.forceEnabledWorkarounds = forceEnabledWorkarounds;
|
2019-06-11 18:11:05 +00:00
|
|
|
newTestParam.forceDisabledWorkarounds = forceDisabledWorkarounds;
|
2019-04-26 07:52:57 +00:00
|
|
|
return newTestParam;
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
DawnTestEnvironment::DawnTestEnvironment(int argc, char** argv) {
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-07-08 03:25:54 +00:00
|
|
|
if (strstr(argv[i], "--adapter-vendor-id") != 0) {
|
|
|
|
const char* value = strchr(argv[i], '=');
|
|
|
|
if (value != nullptr) {
|
|
|
|
mVendorIdFilter = strtoul(value + 1, nullptr, 16);
|
|
|
|
// Set filter flag if vendor id is non-zero.
|
|
|
|
mHasVendorIdFilter = mVendorIdFilter != 0;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-02-21 16:29:12 +00:00
|
|
|
if (strcmp("-h", argv[i]) == 0 || strcmp("--help", argv[i]) == 0) {
|
2019-05-15 06:06:26 +00:00
|
|
|
std::cout << "\n\nUsage: " << argv[0]
|
2019-07-08 03:25:54 +00:00
|
|
|
<< " [GTEST_FLAGS...] [-w] [-d] [-c] [--adapter-vendor-id=x]\n"
|
2019-06-21 02:09:05 +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 "
|
2019-07-08 03:25:54 +00:00
|
|
|
"(defaults to no capture)\n"
|
|
|
|
" --adapter-vendor-id: Select adapter by vendor id to run end2end tests"
|
|
|
|
"on multi-GPU systems \n"
|
2019-06-21 02:09:05 +00:00
|
|
|
<< std::endl;
|
2019-02-21 16:29:12 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DawnTestEnvironment::SetUp() {
|
|
|
|
ASSERT_TRUE(glfwInit());
|
|
|
|
|
|
|
|
mInstance = std::make_unique<dawn_native::Instance>();
|
2019-05-15 06:06:26 +00:00
|
|
|
mInstance->EnableBackendValidation(mEnableBackendValidation);
|
2019-06-21 02:09:05 +00:00
|
|
|
mInstance->EnableBeginCaptureOnStartup(mBeginCaptureOnStartup);
|
2019-02-21 16:29:12 +00:00
|
|
|
|
|
|
|
static constexpr dawn_native::BackendType kAllBackends[] = {
|
2019-04-26 07:52:57 +00:00
|
|
|
dawn_native::BackendType::D3D12,
|
|
|
|
dawn_native::BackendType::Metal,
|
|
|
|
dawn_native::BackendType::OpenGL,
|
|
|
|
dawn_native::BackendType::Vulkan,
|
2019-02-21 16:29:12 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Create a test window for each backend and discover an adapter using it.
|
|
|
|
for (dawn_native::BackendType backend : kAllBackends) {
|
|
|
|
if (detail::IsBackendAvailable(backend)) {
|
|
|
|
CreateBackendWindow(backend);
|
|
|
|
utils::DiscoverAdapter(mInstance.get(), mWindows[backend], backend);
|
|
|
|
}
|
|
|
|
}
|
2019-02-21 17:36:11 +00:00
|
|
|
|
2019-06-21 02:09:05 +00:00
|
|
|
std::cout << "Testing configuration\n"
|
|
|
|
"---------------------\n"
|
|
|
|
"UseWire: "
|
|
|
|
<< (mUseWire ? "true" : "false")
|
|
|
|
<< "\n"
|
|
|
|
"EnableBackendValidation: "
|
|
|
|
<< (mEnableBackendValidation ? "true" : "false")
|
|
|
|
<< "\n"
|
|
|
|
"BeginCaptureOnStartup: "
|
|
|
|
<< (mBeginCaptureOnStartup ? "true" : "false")
|
|
|
|
<< "\n"
|
|
|
|
"\n";
|
2019-02-21 17:36:11 +00:00
|
|
|
|
|
|
|
// Preparing for outputting hex numbers
|
|
|
|
std::cout << std::showbase << std::hex << std::setfill('0') << std::setw(4);
|
|
|
|
|
|
|
|
std::cout << "System adapters: \n";
|
|
|
|
for (const dawn_native::Adapter& adapter : mInstance->GetAdapters()) {
|
|
|
|
const dawn_native::PCIInfo& pci = adapter.GetPCIInfo();
|
|
|
|
|
|
|
|
std::ostringstream vendorId;
|
|
|
|
std::ostringstream deviceId;
|
|
|
|
vendorId << std::setfill('0') << std::uppercase << std::internal << std::hex << std::setw(4)
|
|
|
|
<< pci.vendorId;
|
|
|
|
deviceId << std::setfill('0') << std::uppercase << std::internal << std::hex << std::setw(4)
|
|
|
|
<< pci.deviceId;
|
|
|
|
|
2019-04-15 16:36:25 +00:00
|
|
|
std::cout << " - \"" << pci.name << "\"\n";
|
|
|
|
std::cout << " type: " << DeviceTypeName(adapter.GetDeviceType())
|
|
|
|
<< ", backend: " << ParamName(adapter.GetBackendType()) << "\n";
|
2019-02-21 17:36:11 +00:00
|
|
|
std::cout << " vendorId: 0x" << vendorId.str() << ", deviceId: 0x" << deviceId.str()
|
2019-07-08 03:25:54 +00:00
|
|
|
<< (mHasVendorIdFilter && mVendorIdFilter == pci.vendorId ? " [Selected]" : "")
|
2019-02-21 17:36:11 +00:00
|
|
|
<< "\n";
|
|
|
|
}
|
|
|
|
std::cout << std::endl;
|
2019-02-21 16:29:12 +00:00
|
|
|
}
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
|
|
|
GLFWwindow* DawnTestEnvironment::GetWindowForBackend(dawn_native::BackendType type) const {
|
|
|
|
return mWindows.at(type);
|
2019-02-18 15:07:44 +00:00
|
|
|
}
|
|
|
|
|
2019-07-08 03:25:54 +00:00
|
|
|
bool DawnTestEnvironment::HasVendorIdFilter() const {
|
|
|
|
return mHasVendorIdFilter;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t DawnTestEnvironment::GetVendorIdFilter() const {
|
|
|
|
return mVendorIdFilter;
|
|
|
|
}
|
|
|
|
|
2019-02-21 16:29:12 +00:00
|
|
|
void DawnTestEnvironment::CreateBackendWindow(dawn_native::BackendType type) {
|
|
|
|
glfwDefaultWindowHints();
|
|
|
|
utils::SetupGLFWWindowHintsForBackend(type);
|
|
|
|
|
|
|
|
std::string windowName = "Dawn " + ParamName(type) + " test window";
|
|
|
|
GLFWwindow* window = glfwCreateWindow(400, 400, windowName.c_str(), nullptr, nullptr);
|
|
|
|
|
|
|
|
mWindows[type] = window;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Implementation of DawnTest
|
|
|
|
|
2018-09-06 13:26:48 +00:00
|
|
|
DawnTest::DawnTest() = default;
|
|
|
|
|
2018-07-18 13:18:25 +00:00
|
|
|
DawnTest::~DawnTest() {
|
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();
|
2018-07-18 11:43:49 +00:00
|
|
|
queue = dawn::Queue();
|
|
|
|
swapchain = dawn::SwapChain();
|
|
|
|
device = dawn::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);
|
|
|
|
}
|
|
|
|
|
2018-07-18 13:15:07 +00:00
|
|
|
dawnSetProcs(nullptr);
|
2017-06-16 22:34:35 +00:00
|
|
|
}
|
|
|
|
|
2018-07-18 13:18:25 +00:00
|
|
|
bool DawnTest::IsD3D12() const {
|
2019-04-26 07:52:57 +00:00
|
|
|
return GetParam().backendType == dawn_native::BackendType::D3D12;
|
2017-07-13 00:36:36 +00:00
|
|
|
}
|
|
|
|
|
2018-07-18 13:18:25 +00:00
|
|
|
bool DawnTest::IsMetal() const {
|
2019-04-26 07:52:57 +00:00
|
|
|
return GetParam().backendType == dawn_native::BackendType::Metal;
|
2017-07-18 14:31:50 +00:00
|
|
|
}
|
|
|
|
|
2018-07-18 13:18:25 +00:00
|
|
|
bool DawnTest::IsOpenGL() const {
|
2019-04-26 07:52:57 +00:00
|
|
|
return GetParam().backendType == dawn_native::BackendType::OpenGL;
|
2017-07-18 14:31:50 +00:00
|
|
|
}
|
|
|
|
|
2018-07-18 13:18:25 +00:00
|
|
|
bool DawnTest::IsVulkan() const {
|
2019-04-26 07:52:57 +00:00
|
|
|
return GetParam().backendType == dawn_native::BackendType::Vulkan;
|
2017-07-18 14:31:50 +00:00
|
|
|
}
|
|
|
|
|
2018-09-19 00:32:52 +00:00
|
|
|
bool DawnTest::IsAMD() const {
|
|
|
|
return mPCIInfo.vendorId == kVendorID_AMD;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DawnTest::IsARM() const {
|
|
|
|
return mPCIInfo.vendorId == kVendorID_ARM;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DawnTest::IsImgTec() const {
|
|
|
|
return mPCIInfo.vendorId == kVendorID_ImgTec;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DawnTest::IsIntel() const {
|
|
|
|
return mPCIInfo.vendorId == kVendorID_Intel;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DawnTest::IsNvidia() const {
|
|
|
|
return mPCIInfo.vendorId == kVendorID_Nvidia;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DawnTest::IsQualcomm() const {
|
|
|
|
return mPCIInfo.vendorId == kVendorID_Qualcomm;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DawnTest::IsWindows() const {
|
|
|
|
#ifdef DAWN_PLATFORM_WINDOWS
|
|
|
|
return true;
|
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DawnTest::IsLinux() const {
|
|
|
|
#ifdef DAWN_PLATFORM_LINUX
|
|
|
|
return true;
|
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DawnTest::IsMacOS() const {
|
|
|
|
#ifdef DAWN_PLATFORM_APPLE
|
|
|
|
return true;
|
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-05-01 12:57:27 +00:00
|
|
|
bool DawnTest::UsesWire() const {
|
|
|
|
return gTestEnv->UsesWire();
|
|
|
|
}
|
|
|
|
|
2019-06-25 00:49:56 +00:00
|
|
|
bool DawnTest::IsBackendValidationEnabled() const {
|
|
|
|
return gTestEnv->IsBackendValidationEnabled();
|
|
|
|
}
|
|
|
|
|
2019-07-08 03:25:54 +00:00
|
|
|
bool DawnTest::HasVendorIdFilter() const {
|
|
|
|
return gTestEnv->HasVendorIdFilter();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t DawnTest::GetVendorIdFilter() const {
|
|
|
|
return gTestEnv->GetVendorIdFilter();
|
|
|
|
}
|
|
|
|
|
2018-07-18 13:18:25 +00:00
|
|
|
void DawnTest::SetUp() {
|
2019-02-12 15:48:15 +00:00
|
|
|
// Get an adapter for the backend to use, and create the device.
|
|
|
|
dawn_native::Adapter backendAdapter;
|
2019-04-26 07:52:57 +00:00
|
|
|
const dawn_native::BackendType backendType = GetParam().backendType;
|
2019-02-12 15:48:15 +00:00
|
|
|
{
|
2019-02-21 16:29:12 +00:00
|
|
|
dawn_native::Instance* instance = gTestEnv->GetInstance();
|
|
|
|
std::vector<dawn_native::Adapter> adapters = instance->GetAdapters();
|
2019-02-27 10:09:46 +00:00
|
|
|
|
|
|
|
for (const dawn_native::Adapter& adapter : adapters) {
|
2019-04-26 07:52:57 +00:00
|
|
|
if (adapter.GetBackendType() == backendType) {
|
2019-07-08 03:25:54 +00:00
|
|
|
// TODO(hao.x.li@intel.com): Filter adapter for OpenGL backend once
|
|
|
|
// https://bugs.chromium.org/p/dawn/issues/detail?id=184 is resolved.
|
|
|
|
if (HasVendorIdFilter() && backendType != dawn_native::BackendType::OpenGL) {
|
|
|
|
if (adapter.GetPCIInfo().vendorId == GetVendorIdFilter()) {
|
|
|
|
backendAdapter = adapter;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
backendAdapter = adapter;
|
|
|
|
|
|
|
|
// On Metal, select the last adapter so that the discrete GPU is tested on
|
|
|
|
// multi-GPU systems.
|
|
|
|
// TODO(cwallez@chromium.org): Replace this with command line arguments
|
|
|
|
// requesting a specific device / vendor ID once the macOS 10.13 SDK is rolled
|
|
|
|
// and correct PCI info collection is implemented on Metal.
|
|
|
|
if (backendType != dawn_native::BackendType::Metal) {
|
|
|
|
break;
|
|
|
|
}
|
2019-02-27 10:09:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT(backendAdapter);
|
2019-02-12 15:48:15 +00:00
|
|
|
}
|
2017-06-16 22:34:35 +00:00
|
|
|
|
2019-02-12 15:48:15 +00:00
|
|
|
mPCIInfo = backendAdapter.GetPCIInfo();
|
2019-04-26 07:52:57 +00:00
|
|
|
|
2019-05-29 00:07:37 +00:00
|
|
|
for (const char* forceEnabledWorkaround : GetParam().forceEnabledWorkarounds) {
|
2019-05-11 00:21:50 +00:00
|
|
|
ASSERT(gTestEnv->GetInstance()->GetToggleInfo(forceEnabledWorkaround) != nullptr);
|
2019-04-26 07:52:57 +00:00
|
|
|
}
|
2019-06-11 18:11:05 +00:00
|
|
|
for (const char* forceDisabledWorkaround : GetParam().forceDisabledWorkarounds) {
|
|
|
|
ASSERT(gTestEnv->GetInstance()->GetToggleInfo(forceDisabledWorkaround) != nullptr);
|
|
|
|
}
|
2019-05-29 00:07:37 +00:00
|
|
|
dawn_native::DeviceDescriptor deviceDescriptor;
|
|
|
|
deviceDescriptor.forceEnabledToggles = GetParam().forceEnabledWorkarounds;
|
2019-06-11 18:11:05 +00:00
|
|
|
deviceDescriptor.forceDisabledToggles = GetParam().forceDisabledWorkarounds;
|
2019-05-29 00:07:37 +00:00
|
|
|
backendDevice = backendAdapter.CreateDevice(&deviceDescriptor);
|
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
|
|
|
|
2019-02-21 16:29:12 +00:00
|
|
|
// Get the test window and create the device using it (esp. for OpenGL)
|
2019-04-26 07:52:57 +00:00
|
|
|
GLFWwindow* testWindow = gTestEnv->GetWindowForBackend(backendType);
|
2019-02-21 16:29:12 +00:00
|
|
|
DAWN_ASSERT(testWindow != nullptr);
|
2019-04-26 07:52:57 +00:00
|
|
|
mBinding.reset(utils::CreateBinding(backendType, testWindow, backendDevice));
|
2019-02-12 15:48:15 +00:00
|
|
|
DAWN_ASSERT(mBinding != nullptr);
|
|
|
|
|
2018-06-07 11:10:44 +00:00
|
|
|
// Choose whether to use the backend procs and devices directly, or set up the wire.
|
2019-03-11 16:52:42 +00:00
|
|
|
DawnDevice cDevice = nullptr;
|
|
|
|
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-02-11 21:50:16 +00:00
|
|
|
mWireServer.reset(new dawn_wire::WireServer(backendDevice, backendProcs, mS2cBuf.get()));
|
2018-09-06 13:26:48 +00:00
|
|
|
mC2sBuf->SetHandler(mWireServer.get());
|
2018-06-07 11:10:44 +00:00
|
|
|
|
2019-02-11 21:50:16 +00:00
|
|
|
mWireClient.reset(new dawn_wire::WireClient(mC2sBuf.get()));
|
2019-03-11 16:52:42 +00:00
|
|
|
DawnDevice clientDevice = mWireClient->GetDevice();
|
|
|
|
DawnProcTable clientProcs = mWireClient->GetProcs();
|
2018-09-06 13:26:48 +00:00
|
|
|
mS2cBuf->SetHandler(mWireClient.get());
|
2018-06-07 11:10:44 +00:00
|
|
|
|
|
|
|
procs = clientProcs;
|
|
|
|
cDevice = clientDevice;
|
|
|
|
} else {
|
|
|
|
procs = backendProcs;
|
|
|
|
cDevice = backendDevice;
|
|
|
|
}
|
|
|
|
|
2018-07-18 13:18:25 +00:00
|
|
|
// Set up the device and queue because all tests need them, and DawnTest needs them too for the
|
2018-06-07 11:10:44 +00:00
|
|
|
// deferred expectations.
|
2018-07-18 13:15:07 +00:00
|
|
|
dawnSetProcs(&procs);
|
2018-07-18 11:43:49 +00:00
|
|
|
device = dawn::Device::Acquire(cDevice);
|
2018-06-15 00:26:27 +00:00
|
|
|
queue = device.CreateQueue();
|
2017-06-16 22:34:35 +00:00
|
|
|
|
2018-06-07 11:10:44 +00:00
|
|
|
// The swapchain isn't used by tests but is useful when debugging with graphics debuggers that
|
|
|
|
// capture at frame boundaries.
|
2019-02-15 11:15:58 +00:00
|
|
|
dawn::SwapChainDescriptor swapChainDesc;
|
|
|
|
swapChainDesc.implementation = mBinding->GetSwapChainImplementation();
|
|
|
|
swapchain = device.CreateSwapChain(&swapChainDesc);
|
2019-05-01 12:07:37 +00:00
|
|
|
FlushWire();
|
2018-07-18 13:18:25 +00:00
|
|
|
swapchain.Configure(
|
|
|
|
static_cast<dawn::TextureFormat>(mBinding->GetPreferredSwapChainTextureFormat()),
|
|
|
|
dawn::TextureUsageBit::OutputAttachment, 400, 400);
|
2017-07-28 01:30:57 +00:00
|
|
|
|
2019-05-29 13:03:50 +00:00
|
|
|
device.SetErrorCallback(OnDeviceError, this);
|
2017-06-16 22:34:35 +00:00
|
|
|
}
|
|
|
|
|
2018-07-18 13:18:25 +00:00
|
|
|
void DawnTest::TearDown() {
|
2019-05-01 12:07:37 +00:00
|
|
|
swapchain = dawn::SwapChain();
|
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
|
|
|
}
|
2017-06-16 22:34:35 +00:00
|
|
|
}
|
|
|
|
|
2019-02-28 09:45:48 +00:00
|
|
|
void DawnTest::StartExpectDeviceError() {
|
|
|
|
mExpectError = true;
|
|
|
|
mError = false;
|
|
|
|
}
|
|
|
|
bool DawnTest::EndExpectDeviceError() {
|
|
|
|
mExpectError = false;
|
|
|
|
return mError;
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
2019-05-29 13:03:50 +00:00
|
|
|
void DawnTest::OnDeviceError(const char* message, void* userdata) {
|
|
|
|
DawnTest* self = static_cast<DawnTest*>(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;
|
|
|
|
}
|
|
|
|
|
2018-07-18 13:18:25 +00:00
|
|
|
std::ostringstream& DawnTest::AddBufferExpectation(const char* file,
|
|
|
|
int line,
|
|
|
|
const dawn::Buffer& buffer,
|
2019-04-05 20:51:29 +00:00
|
|
|
uint64_t offset,
|
|
|
|
uint64_t size,
|
2018-07-18 13:18:25 +00:00
|
|
|
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-02-15 12:54:08 +00:00
|
|
|
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
|
|
|
|
encoder.CopyBufferToBuffer(buffer, offset, readback.buffer, readback.offset, size);
|
2017-06-16 22:34:35 +00:00
|
|
|
|
2019-02-15 12:54:08 +00:00
|
|
|
dawn::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;
|
|
|
|
deferred.rowPitch = 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
|
|
|
}
|
|
|
|
|
2018-07-18 13:18:25 +00:00
|
|
|
std::ostringstream& DawnTest::AddTextureExpectation(const char* file,
|
|
|
|
int line,
|
|
|
|
const dawn::Texture& texture,
|
|
|
|
uint32_t x,
|
|
|
|
uint32_t y,
|
|
|
|
uint32_t width,
|
|
|
|
uint32_t height,
|
|
|
|
uint32_t level,
|
2018-12-05 03:22:04 +00:00
|
|
|
uint32_t slice,
|
2018-07-18 13:18:25 +00:00
|
|
|
uint32_t pixelSize,
|
|
|
|
detail::Expectation* expectation) {
|
2017-07-13 19:10:30 +00:00
|
|
|
uint32_t rowPitch = Align(width * pixelSize, kTextureRowPitchAlignment);
|
|
|
|
uint32_t size = rowPitch * (height - 1) + width * pixelSize;
|
2017-06-27 04:11:16 +00:00
|
|
|
|
|
|
|
auto readback = ReserveReadback(size);
|
|
|
|
|
|
|
|
// We need to enqueue the copy immediately because by the time we resolve the expectation,
|
|
|
|
// the texture might have been modified.
|
2018-11-28 17:54:13 +00:00
|
|
|
dawn::TextureCopyView textureCopyView =
|
2018-12-12 09:27:46 +00:00
|
|
|
utils::CreateTextureCopyView(texture, level, slice, {x, y, 0});
|
2018-11-28 17:54:13 +00:00
|
|
|
dawn::BufferCopyView bufferCopyView =
|
|
|
|
utils::CreateBufferCopyView(readback.buffer, readback.offset, rowPitch, 0);
|
|
|
|
dawn::Extent3D copySize = {width, height, 1};
|
2017-06-27 04:11:16 +00:00
|
|
|
|
2019-02-15 12:54:08 +00:00
|
|
|
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
|
|
|
|
encoder.CopyTextureToBuffer(&textureCopyView, &bufferCopyView, ©Size);
|
|
|
|
|
|
|
|
dawn::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;
|
2017-07-13 19:10:30 +00:00
|
|
|
deferred.rowBytes = width * pixelSize;
|
|
|
|
deferred.rowPitch = rowPitch;
|
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
|
|
|
}
|
|
|
|
|
2018-07-18 13:18:25 +00:00
|
|
|
void DawnTest::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);
|
|
|
|
}
|
|
|
|
|
2018-07-18 13:18:25 +00:00
|
|
|
void DawnTest::SwapBuffersForCapture() {
|
2017-07-28 01:30:57 +00:00
|
|
|
// Insert a frame boundary for API capture tools.
|
2018-07-18 11:43:49 +00:00
|
|
|
dawn::Texture backBuffer = swapchain.GetNextTexture();
|
2017-07-28 01:30:57 +00:00
|
|
|
swapchain.Present(backBuffer);
|
2017-07-12 17:17:35 +00:00
|
|
|
}
|
2017-06-27 04:11:16 +00:00
|
|
|
|
2018-07-18 13:18:25 +00:00
|
|
|
void DawnTest::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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-05 20:51:29 +00:00
|
|
|
DawnTest::ReadbackReservation DawnTest::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?
|
2018-08-22 13:37:29 +00:00
|
|
|
dawn::BufferDescriptor descriptor;
|
|
|
|
descriptor.size = readbackSize;
|
2019-07-08 10:05:46 +00:00
|
|
|
descriptor.usage = dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::CopyDst;
|
2018-08-22 13:37:29 +00:00
|
|
|
|
2017-06-16 22:34:35 +00:00
|
|
|
ReadbackSlot slot;
|
|
|
|
slot.bufferSize = readbackSize;
|
2018-08-22 13:37:29 +00:00
|
|
|
slot.buffer = device.CreateBuffer(&descriptor);
|
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;
|
|
|
|
}
|
|
|
|
|
2018-07-18 13:18:25 +00:00
|
|
|
void DawnTest::MapSlotsSynchronously() {
|
|
|
|
// 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
|
|
|
|
2017-11-23 19:51:16 +00:00
|
|
|
auto& slot = mReadbackSlots[i];
|
2019-05-29 13:03:50 +00:00
|
|
|
slot.buffer.MapReadAsync(SlotMapReadCallback, 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
|
2019-03-11 16:52:42 +00:00
|
|
|
void DawnTest::SlotMapReadCallback(DawnBufferMapAsyncStatus status,
|
2018-07-18 13:18:25 +00:00
|
|
|
const void* data,
|
2019-04-05 20:51:29 +00:00
|
|
|
uint64_t,
|
2019-05-29 13:03:50 +00:00
|
|
|
void* userdata_) {
|
2018-07-18 13:12:52 +00:00
|
|
|
DAWN_ASSERT(status == DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS);
|
2017-06-16 22:34:35 +00:00
|
|
|
|
2019-05-29 13:03:50 +00:00
|
|
|
auto userdata = static_cast<MapReadUserdata*>(userdata_);
|
2017-11-23 19:51:16 +00:00
|
|
|
userdata->test->mReadbackSlots[userdata->slot].mappedData = data;
|
2018-07-18 13:18:25 +00:00
|
|
|
userdata->test->mNumPendingMapOperations--;
|
2017-06-16 22:34:35 +00:00
|
|
|
|
|
|
|
delete userdata;
|
|
|
|
}
|
|
|
|
|
2018-07-18 13:18:25 +00:00
|
|
|
void DawnTest::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;
|
|
|
|
if (expectation.rowBytes != expectation.rowPitch) {
|
2018-07-18 11:37:54 +00:00
|
|
|
DAWN_ASSERT(expectation.rowPitch > expectation.rowBytes);
|
2018-07-18 13:18:25 +00:00
|
|
|
uint32_t rowCount =
|
|
|
|
(expectation.size + expectation.rowPitch - 1) / expectation.rowPitch;
|
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) {
|
|
|
|
packedData[i + r * expectation.rowBytes] = data[i + r * expectation.rowPitch];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
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 {
|
2019-02-05 12:17:20 +00:00
|
|
|
bool IsBackendAvailable(dawn_native::BackendType type) {
|
2017-07-12 16:43:24 +00:00
|
|
|
switch (type) {
|
2018-07-18 13:18:25 +00:00
|
|
|
#if defined(DAWN_ENABLE_BACKEND_D3D12)
|
2019-02-05 12:17:20 +00:00
|
|
|
case dawn_native::BackendType::D3D12:
|
2018-07-18 13:18:25 +00:00
|
|
|
#endif
|
|
|
|
#if defined(DAWN_ENABLE_BACKEND_METAL)
|
2019-02-05 12:17:20 +00:00
|
|
|
case dawn_native::BackendType::Metal:
|
2018-07-18 13:18:25 +00:00
|
|
|
#endif
|
|
|
|
#if defined(DAWN_ENABLE_BACKEND_OPENGL)
|
2019-02-05 12:17:20 +00:00
|
|
|
case dawn_native::BackendType::OpenGL:
|
2018-07-18 13:18:25 +00:00
|
|
|
#endif
|
|
|
|
#if defined(DAWN_ENABLE_BACKEND_VULKAN)
|
2019-02-05 12:17:20 +00:00
|
|
|
case dawn_native::BackendType::Vulkan:
|
2018-07-18 13:18:25 +00:00
|
|
|
#endif
|
2017-07-12 16:43:24 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
2017-06-16 22:34:35 +00:00
|
|
|
}
|
|
|
|
|
2019-04-26 07:52:57 +00:00
|
|
|
std::vector<DawnTestParam> FilterBackends(const DawnTestParam* params, size_t numParams) {
|
|
|
|
std::vector<DawnTestParam> backends;
|
2017-06-16 22:34:35 +00:00
|
|
|
|
|
|
|
for (size_t i = 0; i < numParams; ++i) {
|
2019-04-26 07:52:57 +00:00
|
|
|
if (IsBackendAvailable(params[i].backendType)) {
|
|
|
|
backends.push_back(params[i]);
|
2017-06-16 22:34:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return backends;
|
|
|
|
}
|
|
|
|
|
2019-04-26 07:52:57 +00:00
|
|
|
std::string GetParamName(const testing::TestParamInfo<DawnTestParam>& info) {
|
|
|
|
std::ostringstream ostream;
|
|
|
|
ostream << ParamName(info.param.backendType);
|
|
|
|
|
2019-05-29 00:07:37 +00:00
|
|
|
for (const char* forceEnabledWorkaround : info.param.forceEnabledWorkarounds) {
|
|
|
|
ostream << "_" << forceEnabledWorkaround;
|
2019-04-26 07:52:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ostream.str();
|
2019-02-05 12:17:20 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
|
|
auto printBuffer = [&](const T* buffer) {
|
|
|
|
static constexpr unsigned int kBytes = sizeof(T);
|
|
|
|
|
2017-11-23 19:51:16 +00:00
|
|
|
for (size_t index = 0; index < mExpected.size(); ++index) {
|
2017-07-17 13:37:46 +00:00
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
2017-11-23 19:51:16 +00:00
|
|
|
if (mExpected.size() <= 1024) {
|
2017-07-17 13:37:46 +00:00
|
|
|
result << "Expected:" << std::endl;
|
2017-11-23 19:51:16 +00:00
|
|
|
printBuffer(mExpected.data());
|
2017-07-17 13:37:46 +00:00
|
|
|
|
|
|
|
result << "Actual:" << std::endl;
|
|
|
|
printBuffer(actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
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>;
|
2017-06-16 22:34:35 +00:00
|
|
|
template class ExpectEq<uint32_t>;
|
2017-06-27 04:11:16 +00:00
|
|
|
template class ExpectEq<RGBA8>;
|
2018-07-18 13:18:25 +00:00
|
|
|
} // namespace detail
|