DawnTest: Gather adapters on environment creation for filtering backends

This moves the creation of the Instance and Adapter discover to
environment creation. It allows programatically filtering test
parameterizations based on what is available on the system instead of
relying on what is enabled at compile time.

Because of an issue with the Vulkan validation layers, the instance and
adapters are created twice. Once in environment creation, and once on
environment set up. The Vulkan validation layers use static global
mutexes which are unsafe when Chromium's test launcher forks the
launcher process between environment creation and SetUp.

Bug: dawn:396
Change-Id: Id79f0d274331e4ba95f75b2ca4e896ad0f7a31a8
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/21762
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Stephen White <senorblanco@chromium.org>
This commit is contained in:
Austin Eng 2020-05-15 16:07:12 +00:00 committed by Commit Bot service account
parent 5133221139
commit 25c747cf08
4 changed files with 66 additions and 41 deletions

View File

@ -128,6 +128,11 @@ DawnTestParam VulkanBackend(std::initializer_list<const char*> forceEnabledWorka
forceDisabledWorkarounds);
}
TestAdapterProperties::TestAdapterProperties(const wgpu::AdapterProperties& properties,
bool selected)
: wgpu::AdapterProperties(properties), adapterName(properties.name), selected(selected) {
}
std::ostream& operator<<(std::ostream& os, const DawnTestParam& param) {
os << ParamName(param.backendType);
for (const char* forceEnabledWorkaround : param.forceEnabledWorkarounds) {
@ -152,6 +157,21 @@ void DawnTestEnvironment::SetEnvironment(DawnTestEnvironment* env) {
}
DawnTestEnvironment::DawnTestEnvironment(int argc, char** argv) {
ParseArgs(argc, argv);
// Create a temporary instance to gather adapter properties. This is done before
// test instantiation so FilterBackends can generate test parameterizations only on available
// backends. 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.
std::unique_ptr<dawn_native::Instance> instance = CreateInstanceAndDiscoverAdapters();
ASSERT(instance);
GatherAdapterProperties(instance.get());
PrintTestConfigurationAndAdapterInfo();
}
void DawnTestEnvironment::ParseArgs(int argc, char** argv) {
size_t argLen = 0; // Set when parsing --arg=X arguments
for (int i = 1; i < argc; ++i) {
if (strcmp("-w", argv[i]) == 0 || strcmp("--use-wire", argv[i]) == 0) {
@ -319,6 +339,30 @@ std::unique_ptr<dawn_native::Instance> DawnTestEnvironment::CreateInstanceAndDis
return instance;
}
void DawnTestEnvironment::GatherAdapterProperties(const dawn_native::Instance* instance) {
for (const dawn_native::Adapter& adapter : instance->GetAdapters()) {
wgpu::AdapterProperties properties;
adapter.GetProperties(&properties);
mAdapterProperties.emplace_back(
properties, mHasVendorIdFilter && mVendorIdFilter == properties.vendorID);
}
}
std::vector<DawnTestParam> DawnTestEnvironment::FilterBackends(const DawnTestParam* params,
size_t numParams) const {
std::vector<DawnTestParam> backends;
for (size_t i = 0; i < numParams; ++i) {
for (const auto& adapterProperties : mAdapterProperties) {
if (params[i].backendType == adapterProperties.backendType) {
backends.push_back(params[i]);
break;
}
}
}
return backends;
}
void DawnTestEnvironment::PrintTestConfigurationAndAdapterInfo() const {
dawn::LogMessage log = dawn::InfoLog();
log << "Testing configuration\n"
@ -344,9 +388,7 @@ void DawnTestEnvironment::PrintTestConfigurationAndAdapterInfo() const {
"\n"
<< "System adapters: \n";
for (const dawn_native::Adapter& adapter : mInstance->GetAdapters()) {
wgpu::AdapterProperties properties;
adapter.GetProperties(&properties);
for (const TestAdapterProperties& properties : mAdapterProperties) {
std::ostringstream vendorId;
std::ostringstream deviceId;
vendorId << std::setfill('0') << std::uppercase << std::internal << std::hex << std::setw(4)
@ -357,19 +399,17 @@ void DawnTestEnvironment::PrintTestConfigurationAndAdapterInfo() const {
// Preparing for outputting hex numbers
log << std::showbase << std::hex << std::setfill('0') << std::setw(4)
<< " - \"" << properties.name << "\"\n"
<< " - \"" << properties.adapterName << "\"\n"
<< " type: " << AdapterTypeName(properties.adapterType)
<< ", backend: " << ParamName(properties.backendType) << "\n"
<< " vendorId: 0x" << vendorId.str() << ", deviceId: 0x" << deviceId.str()
<< (mHasVendorIdFilter && mVendorIdFilter == properties.vendorID ? " [Selected]" : "")
<< "\n";
<< (properties.selected ? " [Selected]" : "") << "\n";
}
}
void DawnTestEnvironment::SetUp() {
mInstance = CreateInstanceAndDiscoverAdapters();
ASSERT(mInstance);
PrintTestConfigurationAndAdapterInfo();
}
void DawnTestEnvironment::TearDown() {
@ -987,39 +1027,9 @@ std::ostream& operator<<(std::ostream& stream, const RGBA8& color) {
}
namespace detail {
bool IsBackendAvailable(wgpu::BackendType type) {
switch (type) {
#if defined(DAWN_ENABLE_BACKEND_D3D12)
case wgpu::BackendType::D3D12:
#endif
#if defined(DAWN_ENABLE_BACKEND_METAL)
case wgpu::BackendType::Metal:
#endif
#if defined(DAWN_ENABLE_BACKEND_NULL)
case wgpu::BackendType::Null:
#endif
#if defined(DAWN_ENABLE_BACKEND_OPENGL)
case wgpu::BackendType::OpenGL:
#endif
#if defined(DAWN_ENABLE_BACKEND_VULKAN)
case wgpu::BackendType::Vulkan:
#endif
return true;
default:
return false;
}
}
std::vector<DawnTestParam> FilterBackends(const DawnTestParam* params, size_t numParams) {
std::vector<DawnTestParam> backends;
for (size_t i = 0; i < numParams; ++i) {
if (IsBackendAvailable(params[i].backendType)) {
backends.push_back(params[i]);
}
}
return backends;
ASSERT(gTestEnv != nullptr);
return gTestEnv->FilterBackends(params, numParams);
}
// Helper classes to set expectations

View File

@ -89,6 +89,16 @@ struct RGBA8 {
};
std::ostream& operator<<(std::ostream& stream, const RGBA8& color);
struct TestAdapterProperties : wgpu::AdapterProperties {
TestAdapterProperties(const wgpu::AdapterProperties& properties, bool selected);
std::string adapterName;
bool selected;
private:
// This may be temporary, so it is copied into |adapterName| and made private.
using wgpu::AdapterProperties::name;
};
struct DawnTestParam {
DawnTestParam(wgpu::BackendType backendType,
std::initializer_list<const char*> forceEnabledWorkarounds = {},
@ -140,6 +150,8 @@ class DawnTestEnvironment : public testing::Environment {
static void SetEnvironment(DawnTestEnvironment* env);
std::vector<DawnTestParam> FilterBackends(const DawnTestParam* params, size_t numParams) const;
void SetUp() override;
void TearDown() override;
@ -157,7 +169,9 @@ class DawnTestEnvironment : public testing::Environment {
std::unique_ptr<dawn_native::Instance> mInstance;
private:
void ParseArgs(int argc, char** argv);
std::unique_ptr<dawn_native::Instance> CreateInstanceAndDiscoverAdapters() const;
void GatherAdapterProperties(const dawn_native::Instance* instance);
void PrintTestConfigurationAndAdapterInfo() const;
bool mUseWire = false;
@ -171,6 +185,7 @@ class DawnTestEnvironment : public testing::Environment {
bool mHasVendorIdFilter = false;
uint32_t mVendorIdFilter = 0;
std::string mWireTraceDir;
std::vector<TestAdapterProperties> mAdapterProperties;
};
class DawnTestBase {

View File

@ -15,7 +15,7 @@
#include "tests/DawnTest.h"
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
InitDawnEnd2EndTestEnvironment(argc, argv);
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -15,7 +15,7 @@
#include "tests/perf_tests/DawnPerfTest.h"
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
InitDawnPerfTestEnvironment(argc, argv);
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}