From ac67fec1c9751543884e9c66a094d4665e406462 Mon Sep 17 00:00:00 2001 From: Corentin Wallez Date: Fri, 4 Jan 2019 10:30:40 +0000 Subject: [PATCH] dawn_native: Add Instance and Adapters New objects are introduced to control what happens before device creation in dawn_native: - Instance: a connection from the application to dawn_native that is used for dependency injection and to discover adapters. - Adapters: represents the possibility of device creation for a specific (GPU, backend) pair. - BackendConnection: an internal object that standardizes the interface between the frontend and backends. The BackendConnection interface is implemented for the Null backend and stubbed out in other backends. This allows this change to port the ValidationTests to use the new Instance and Adapters concept and deal with other backends later. BUG=dawn:29 Change-Id: I19719a9342b4af091accc0c02fb6b9697eadde7b Reviewed-on: https://dawn-review.googlesource.com/c/3500 Reviewed-by: Stephen White Reviewed-by: Kai Ninomiya Reviewed-by: Corentin Wallez Commit-Queue: Corentin Wallez --- BUILD.gn | 6 + src/dawn_native/Adapter.cpp | 54 ++++++++ src/dawn_native/Adapter.h | 49 ++++++++ src/dawn_native/BackendConnection.cpp | 31 +++++ src/dawn_native/BackendConnection.h | 44 +++++++ src/dawn_native/DawnNative.cpp | 47 +++++++ src/dawn_native/Device.h | 6 +- src/dawn_native/Instance.cpp | 119 ++++++++++++++++++ src/dawn_native/Instance.h | 53 ++++++++ src/dawn_native/d3d12/DeviceD3D12.cpp | 5 + src/dawn_native/metal/DeviceMTL.mm | 5 + src/dawn_native/null/NullBackend.cpp | 33 +++++ src/dawn_native/opengl/DeviceGL.cpp | 5 + src/dawn_native/vulkan/DeviceVk.cpp | 5 + src/include/dawn_native/DawnNative.h | 61 +++++++++ .../unittests/validation/ValidationTest.cpp | 29 +++-- .../unittests/validation/ValidationTest.h | 6 + 17 files changed, 546 insertions(+), 12 deletions(-) create mode 100644 src/dawn_native/Adapter.cpp create mode 100644 src/dawn_native/Adapter.h create mode 100644 src/dawn_native/BackendConnection.cpp create mode 100644 src/dawn_native/BackendConnection.h create mode 100644 src/dawn_native/Instance.cpp create mode 100644 src/dawn_native/Instance.h diff --git a/BUILD.gn b/BUILD.gn index 9a8fe4c72f..2673ebe58d 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -359,6 +359,10 @@ source_set("libdawn_native_sources") { sources = get_target_outputs(":libdawn_native_utils_gen") sources += [ + "src/dawn_native/Adapter.cpp", + "src/dawn_native/Adapter.h", + "src/dawn_native/BackendConnection.cpp", + "src/dawn_native/BackendConnection.h", "src/dawn_native/BindGroup.cpp", "src/dawn_native/BindGroup.h", "src/dawn_native/BindGroupLayout.cpp", @@ -393,6 +397,8 @@ source_set("libdawn_native_sources") { "src/dawn_native/Forward.h", "src/dawn_native/InputState.cpp", "src/dawn_native/InputState.h", + "src/dawn_native/Instance.cpp", + "src/dawn_native/Instance.h", "src/dawn_native/ObjectBase.cpp", "src/dawn_native/ObjectBase.h", "src/dawn_native/PassResourceUsage.h", diff --git a/src/dawn_native/Adapter.cpp b/src/dawn_native/Adapter.cpp new file mode 100644 index 0000000000..137a1c7e70 --- /dev/null +++ b/src/dawn_native/Adapter.cpp @@ -0,0 +1,54 @@ +// Copyright 2018 The Dawn Authors +// +// 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. + +#include "dawn_native/Adapter.h" + +#include "dawn_native/Instance.h" + +namespace dawn_native { + + AdapterBase::AdapterBase(InstanceBase* instance, BackendType backend) + : mInstance(instance), mBackend(backend) { + } + + BackendType AdapterBase::GetBackendType() const { + return mBackend; + } + + const PCIInfo& AdapterBase::GetPCIInfo() const { + return mPCIInfo; + } + + InstanceBase* AdapterBase::GetInstance() const { + return mInstance; + } + + DeviceBase* AdapterBase::CreateDevice() { + DeviceBase* result = nullptr; + + if (mInstance->ConsumedError(CreateDeviceInternal(&result))) { + return nullptr; + } + + return result; + } + + MaybeError AdapterBase::CreateDeviceInternal(DeviceBase** result) { + // TODO(cwallez@chromium.org): This will eventually have validation that the device + // descriptor is valid and is a subset what's allowed on this adapter. + DAWN_TRY_ASSIGN(*result, CreateDeviceImpl()); + return {}; + } + +} // namespace dawn_native diff --git a/src/dawn_native/Adapter.h b/src/dawn_native/Adapter.h new file mode 100644 index 0000000000..afb754619c --- /dev/null +++ b/src/dawn_native/Adapter.h @@ -0,0 +1,49 @@ +// Copyright 2018 The Dawn Authors +// +// 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. + +#ifndef DAWNNATIVE_ADAPTER_H_ +#define DAWNNATIVE_ADAPTER_H_ + +#include "dawn_native/DawnNative.h" + +#include "dawn_native/Error.h" + +namespace dawn_native { + + class DeviceBase; + + class AdapterBase { + public: + AdapterBase(InstanceBase* instance, BackendType backend); + virtual ~AdapterBase() = default; + + BackendType GetBackendType() const; + const PCIInfo& GetPCIInfo() const; + InstanceBase* GetInstance() const; + + DeviceBase* CreateDevice(); + + private: + virtual ResultOrError CreateDeviceImpl() = 0; + + MaybeError CreateDeviceInternal(DeviceBase** result); + + InstanceBase* mInstance = nullptr; + BackendType mBackend; + PCIInfo mPCIInfo; + }; + +} // namespace dawn_native + +#endif // DAWNNATIVE_ADAPTER_H_ diff --git a/src/dawn_native/BackendConnection.cpp b/src/dawn_native/BackendConnection.cpp new file mode 100644 index 0000000000..93356ff6b8 --- /dev/null +++ b/src/dawn_native/BackendConnection.cpp @@ -0,0 +1,31 @@ +// Copyright 2018 The Dawn Authors +// +// 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. + +#include "dawn_native/BackendConnection.h" + +namespace dawn_native { + + BackendConnection::BackendConnection(InstanceBase* instance, BackendType type) + : mInstance(instance), mType(type) { + } + + BackendType BackendConnection::GetType() const { + return mType; + } + + InstanceBase* BackendConnection::GetInstance() const { + return mInstance; + } + +} // namespace dawn_native diff --git a/src/dawn_native/BackendConnection.h b/src/dawn_native/BackendConnection.h new file mode 100644 index 0000000000..c3d6fe797e --- /dev/null +++ b/src/dawn_native/BackendConnection.h @@ -0,0 +1,44 @@ +// Copyright 2018 The Dawn Authors +// +// 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. + +#ifndef DAWNNATIVE_BACKENDCONNECTION_H_ +#define DAWNNATIVE_BACKENDCONNECTION_H_ + +#include "dawn_native/Adapter.h" +#include "dawn_native/DawnNative.h" + +namespace dawn_native { + + // An common interface for all backends. Mostly used to create adapters for a particular + // backend. + class BackendConnection { + public: + BackendConnection(InstanceBase* instance, BackendType type); + virtual ~BackendConnection() = default; + + BackendType GetType() const; + InstanceBase* GetInstance() const; + + // Returns all the adapters for the system that can be created by the backend, without extra + // options (such as debug adapters, custom driver libraries, etc.) + virtual std::vector> DiscoverDefaultAdapters() = 0; + + private: + InstanceBase* mInstance = nullptr; + BackendType mType; + }; + +} // namespace dawn_native + +#endif // DAWNNATIVE_BACKENDCONNECTION_H_ diff --git a/src/dawn_native/DawnNative.cpp b/src/dawn_native/DawnNative.cpp index f1dd1aa423..6bd7bb876f 100644 --- a/src/dawn_native/DawnNative.cpp +++ b/src/dawn_native/DawnNative.cpp @@ -14,6 +14,7 @@ #include "dawn_native/DawnNative.h" #include "dawn_native/Device.h" +#include "dawn_native/Instance.h" // Contains the entry-points into dawn_native @@ -30,4 +31,50 @@ namespace dawn_native { return deviceBase->GetPCIInfo(); } + // Adapter + + Adapter::Adapter() = default; + + Adapter::Adapter(AdapterBase* impl) : mImpl(impl) { + } + + Adapter::~Adapter() { + mImpl = nullptr; + } + + BackendType Adapter::GetBackendType() const { + return mImpl->GetBackendType(); + } + + const PCIInfo& Adapter::GetPCIInfo() const { + return mImpl->GetPCIInfo(); + } + + dawnDevice Adapter::CreateDevice() { + return reinterpret_cast(mImpl->CreateDevice()); + } + + // Instance + + Instance::Instance() : mImpl(new InstanceBase()) { + } + + Instance::~Instance() { + delete mImpl; + mImpl = nullptr; + } + + void Instance::DiscoverDefaultAdapters() { + mImpl->DiscoverDefaultAdapters(); + } + + std::vector Instance::GetAdapters() const { + // Adapters are owned by mImpl so it is safe to return non RAII pointers to them + std::vector adapters; + for (const std::unique_ptr& adapter : mImpl->GetAdapters()) { + adapters.push_back({adapter.get()}); + } + return adapters; + } + } // namespace dawn_native diff --git a/src/dawn_native/Device.h b/src/dawn_native/Device.h index 79e1a350e4..491ae19957 100644 --- a/src/dawn_native/Device.h +++ b/src/dawn_native/Device.h @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef DAWNNATIVE_DEVICEBASE_H_ -#define DAWNNATIVE_DEVICEBASE_H_ +#ifndef DAWNNATIVE_DEVICE_H_ +#define DAWNNATIVE_DEVICE_H_ #include "common/Serial.h" #include "dawn_native/Error.h" @@ -170,4 +170,4 @@ namespace dawn_native { } // namespace dawn_native -#endif // DAWNNATIVE_DEVICEBASE_H_ +#endif // DAWNNATIVE_DEVICE_H_ diff --git a/src/dawn_native/Instance.cpp b/src/dawn_native/Instance.cpp new file mode 100644 index 0000000000..595f442fe9 --- /dev/null +++ b/src/dawn_native/Instance.cpp @@ -0,0 +1,119 @@ +// Copyright 2018 The Dawn Authors +// +// 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. + +#include "dawn_native/Instance.h" + +#include "common/Assert.h" +#include "dawn_native/ErrorData.h" + +#include + +namespace dawn_native { + + // Forward definitions of each backend's "Connect" function that creates new BackendConnection. + // Conditionally compiled declarations are used to avoid using static constructors instead. +#if defined(DAWN_ENABLE_BACKEND_D3D12) + namespace d3d12 { + BackendConnection* Connect(InstanceBase* instance); + } +#endif // defined(DAWN_ENABLE_BACKEND_D3D12) +#if defined(DAWN_ENABLE_BACKEND_METAL) + namespace metal { + BackendConnection* Connect(InstanceBase* instance); + } +#endif // defined(DAWN_ENABLE_BACKEND_METAL) +#if defined(DAWN_ENABLE_BACKEND_NULL) + namespace null { + BackendConnection* Connect(InstanceBase* instance); + } +#endif // defined(DAWN_ENABLE_BACKEND_NULL) +#if defined(DAWN_ENABLE_BACKEND_OPENGL) + namespace opengl { + BackendConnection* Connect(InstanceBase* instance); + } +#endif // defined(DAWN_ENABLE_BACKEND_OPENGL) +#if defined(DAWN_ENABLE_BACKEND_VULKAN) + namespace vulkan { + BackendConnection* Connect(InstanceBase* instance); + } +#endif // defined(DAWN_ENABLE_BACKEND_VULKAN) + + // InstanceBase + + void InstanceBase::DiscoverDefaultAdapters() { + EnsureBackendConnections(); + + // Query and merge all default adapters for all backends + for (std::unique_ptr& backend : mBackends) { + std::vector> backendAdapters = + backend->DiscoverDefaultAdapters(); + + for (std::unique_ptr& adapter : backendAdapters) { + ASSERT(adapter->GetBackendType() == backend->GetType()); + ASSERT(adapter->GetInstance() == this); + mAdapters.push_back(std::move(adapter)); + } + } + } + + const std::vector>& InstanceBase::GetAdapters() const { + return mAdapters; + } + + void InstanceBase::EnsureBackendConnections() { + if (mBackendsConnected) { + return; + } + + auto Register = [this](BackendConnection* connection, BackendType expectedType) { + if (connection != nullptr) { + ASSERT(connection->GetType() == expectedType); + ASSERT(connection->GetInstance() == this); + mBackends.push_back(std::unique_ptr(connection)); + } + }; + +#if defined(DAWN_ENABLE_BACKEND_D3D12) + Register(d3d12::Connect(this), BackendType::D3D12); +#endif // defined(DAWN_ENABLE_BACKEND_D3D12) +#if defined(DAWN_ENABLE_BACKEND_METAL) + Register(metal::Connect(this), BackendType::Metal); +#endif // defined(DAWN_ENABLE_BACKEND_METAL) +#if defined(DAWN_ENABLE_BACKEND_NULL) + Register(null::Connect(this), BackendType::Null); +#endif // defined(DAWN_ENABLE_BACKEND_NULL) +#if defined(DAWN_ENABLE_BACKEND_OPENGL) + Register(opengl::Connect(this), BackendType::OpenGL); +#endif // defined(DAWN_ENABLE_BACKEND_OPENGL) +#if defined(DAWN_ENABLE_BACKEND_VULKAN) + Register(vulkan::Connect(this), BackendType::Vulkan); +#endif // defined(DAWN_ENABLE_BACKEND_VULKAN) + + mBackendsConnected = true; + } + + bool InstanceBase::ConsumedError(MaybeError maybeError) { + if (maybeError.IsError()) { + ErrorData* error = maybeError.AcquireError(); + + ASSERT(error != nullptr); + std::cout << error->GetMessage() << std::endl; + delete error; + + return true; + } + return false; + } + +} // namespace dawn_native diff --git a/src/dawn_native/Instance.h b/src/dawn_native/Instance.h new file mode 100644 index 0000000000..7fc4128b8d --- /dev/null +++ b/src/dawn_native/Instance.h @@ -0,0 +1,53 @@ +// Copyright 2018 The Dawn Authors +// +// 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. + +#ifndef DAWNNATIVE_INSTANCE_H_ +#define DAWNNATIVE_INSTANCE_H_ + +#include "dawn_native/Adapter.h" +#include "dawn_native/BackendConnection.h" + +#include +#include + +namespace dawn_native { + + // This is called InstanceBase for consistency across the frontend, even if the backends don't + // specialize this class. + class InstanceBase final { + public: + InstanceBase() = default; + ~InstanceBase() = default; + + InstanceBase(const InstanceBase& other) = delete; + InstanceBase& operator=(const InstanceBase& other) = delete; + + void DiscoverDefaultAdapters(); + + const std::vector>& GetAdapters() const; + + // Used to handle error that happen up to device creation. + bool ConsumedError(MaybeError maybeError); + + private: + void EnsureBackendConnections(); + bool mBackendsConnected = false; + + std::vector> mBackends; + std::vector> mAdapters; + }; + +} // namespace dawn_native + +#endif // DAWNNATIVE_INSTANCE_H_ diff --git a/src/dawn_native/d3d12/DeviceD3D12.cpp b/src/dawn_native/d3d12/DeviceD3D12.cpp index 2d9f6beb5b..dcf7110386 100644 --- a/src/dawn_native/d3d12/DeviceD3D12.cpp +++ b/src/dawn_native/d3d12/DeviceD3D12.cpp @@ -16,6 +16,7 @@ #include "common/Assert.h" #include "common/SwapChainUtils.h" +#include "dawn_native/BackendConnection.h" #include "dawn_native/D3D12Backend.h" #include "dawn_native/d3d12/BindGroupD3D12.h" #include "dawn_native/d3d12/BindGroupLayoutD3D12.h" @@ -66,6 +67,10 @@ namespace dawn_native { namespace d3d12 { ASSERT(SUCCEEDED(hr)); } + BackendConnection* Connect(InstanceBase* instance) { + return nullptr; + } + namespace { ComPtr CreateFactory(const PlatformFunctions* functions) { ComPtr factory; diff --git a/src/dawn_native/metal/DeviceMTL.mm b/src/dawn_native/metal/DeviceMTL.mm index b11018a104..1e54f5fd24 100644 --- a/src/dawn_native/metal/DeviceMTL.mm +++ b/src/dawn_native/metal/DeviceMTL.mm @@ -14,6 +14,7 @@ #include "dawn_native/metal/DeviceMTL.h" +#include "dawn_native/BackendConnection.h" #include "dawn_native/BindGroup.h" #include "dawn_native/BindGroupLayout.h" #include "dawn_native/MetalBackend.h" @@ -125,6 +126,10 @@ namespace dawn_native { namespace metal { return reinterpret_cast(new Device(metalDevice)); } + BackendConnection* Connect(InstanceBase* instance) { + return nullptr; + } + // Device Device::Device(id mtlDevice) diff --git a/src/dawn_native/null/NullBackend.cpp b/src/dawn_native/null/NullBackend.cpp index aa3ec7fb9a..01ca980121 100644 --- a/src/dawn_native/null/NullBackend.cpp +++ b/src/dawn_native/null/NullBackend.cpp @@ -14,6 +14,7 @@ #include "dawn_native/null/NullBackend.h" +#include "dawn_native/BackendConnection.h" #include "dawn_native/Commands.h" #include "dawn_native/NullBackend.h" @@ -21,10 +22,42 @@ namespace dawn_native { namespace null { + // Implementation of pre-Device objects: the null adapter, null backend connection and Connect() + + class Adapter : public AdapterBase { + public: + Adapter(InstanceBase* instance) : AdapterBase(instance, BackendType::Null) { + } + virtual ~Adapter() = default; + + private: + ResultOrError CreateDeviceImpl() override { + return {new Device}; + } + }; + + class NullBackend : public BackendConnection { + public: + NullBackend(InstanceBase* instance) : BackendConnection(instance, BackendType::Null) { + } + + std::vector> DiscoverDefaultAdapters() override { + // There is always a single Null adapter because it is purely CPU based and doesn't + // depend on the system. + std::vector> adapters; + adapters.push_back(std::make_unique(GetInstance())); + return adapters; + } + }; + dawnDevice CreateDevice() { return reinterpret_cast(new Device); } + BackendConnection* Connect(InstanceBase* instance) { + return new NullBackend(instance); + } + // Device Device::Device() { diff --git a/src/dawn_native/opengl/DeviceGL.cpp b/src/dawn_native/opengl/DeviceGL.cpp index 7afd520a82..833f7e23f4 100644 --- a/src/dawn_native/opengl/DeviceGL.cpp +++ b/src/dawn_native/opengl/DeviceGL.cpp @@ -14,6 +14,7 @@ #include "dawn_native/opengl/DeviceGL.h" +#include "dawn_native/BackendConnection.h" #include "dawn_native/BindGroup.h" #include "dawn_native/BindGroupLayout.h" #include "dawn_native/OpenGLBackend.h" @@ -42,6 +43,10 @@ namespace dawn_native { namespace opengl { return reinterpret_cast(new Device); } + BackendConnection* Connect(InstanceBase* instance) { + return nullptr; + } + // Device Device::Device() { diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp index 074f334d61..725df61f77 100644 --- a/src/dawn_native/vulkan/DeviceVk.cpp +++ b/src/dawn_native/vulkan/DeviceVk.cpp @@ -16,6 +16,7 @@ #include "common/Platform.h" #include "common/SwapChainUtils.h" +#include "dawn_native/BackendConnection.h" #include "dawn_native/Commands.h" #include "dawn_native/ErrorData.h" #include "dawn_native/VulkanBackend.h" @@ -80,6 +81,10 @@ namespace dawn_native { namespace vulkan { return static_cast(impl->GetPreferredFormat()); } + BackendConnection* Connect(InstanceBase* instance) { + return nullptr; + } + // Device Device::Device(const std::vector& requiredInstanceExtensions) { diff --git a/src/include/dawn_native/DawnNative.h b/src/include/dawn_native/DawnNative.h index f90dc9eaa6..842e554d56 100644 --- a/src/include/dawn_native/DawnNative.h +++ b/src/include/dawn_native/DawnNative.h @@ -19,14 +19,75 @@ #include #include +#include namespace dawn_native { + struct PCIInfo { uint32_t deviceId = 0; uint32_t vendorId = 0; std::string name; }; + enum class BackendType { + D3D12, + Metal, + Null, + OpenGL, + Vulkan, + }; + + class InstanceBase; + class AdapterBase; + + // An adapter is an object that represent on possibility of creating devices in the system. + // Most of the time it will represent a combination of a physical GPU and an API. Not that the + // same GPU can be represented by multiple adapters but on different APIs. + // + // The underlying Dawn adapter is owned by the Dawn instance so this class is not RAII but just + // a reference to an underlying adapter. + class DAWN_NATIVE_EXPORT Adapter { + public: + Adapter(); + Adapter(AdapterBase* impl); + ~Adapter(); + + BackendType GetBackendType() const; + const PCIInfo& GetPCIInfo() const; + + // Create a device on this adapter, note that the interface will change to include at least + // a device descriptor and a pointer to backend specific options. + // On an error, nullptr is returned. + dawnDevice CreateDevice(); + + private: + AdapterBase* mImpl = nullptr; + }; + + // Represents a connection to dawn_native and is used for dependency injection, discovering + // system adapters and injecting custom adapters (like a Swiftshader Vulkan adapter). + // + // This is an RAII class for Dawn instances and also controls the lifetime of all adapters + // for this instance. + class DAWN_NATIVE_EXPORT Instance { + public: + Instance(); + ~Instance(); + + Instance(const Instance& other) = delete; + Instance& operator=(const Instance& other) = delete; + + // Gather all adapters in the system that can be accessed with no special options. These + // adapters will later be returned by GetAdapters. + void DiscoverDefaultAdapters(); + + // Returns all the adapters that the instance knows about. + std::vector GetAdapters() const; + + private: + InstanceBase* mImpl = nullptr; + }; + // Backend-agnostic API for dawn_native DAWN_NATIVE_EXPORT dawnProcTable GetProcs(); diff --git a/src/tests/unittests/validation/ValidationTest.cpp b/src/tests/unittests/validation/ValidationTest.cpp index 903057aef4..b821088553 100644 --- a/src/tests/unittests/validation/ValidationTest.cpp +++ b/src/tests/unittests/validation/ValidationTest.cpp @@ -14,22 +14,33 @@ #include "tests/unittests/validation/ValidationTest.h" +#include "common/Assert.h" #include "dawn/dawn.h" #include "dawn_native/DawnNative.h" #include "dawn_native/NullBackend.h" -namespace dawn_native { - namespace null { - void Init(dawnProcTable* procs, dawnDevice* device); - } -} - ValidationTest::ValidationTest() { - dawnProcTable procs = dawn_native::GetProcs(); - dawnDevice cDevice = dawn_native::null::CreateDevice(); + mInstance = std::make_unique(); + mInstance->DiscoverDefaultAdapters(); + std::vector adapters = mInstance->GetAdapters(); + + // Validation tests run against the null backend, find the corresponding adapter + bool foundNullAdapter = false; + dawn_native::Adapter nullAdapter; + for (auto adapter : adapters) { + if (adapter.GetBackendType() == dawn_native::BackendType::Null) { + nullAdapter = adapter; + foundNullAdapter = true; + break; + } + } + + ASSERT(foundNullAdapter); + device = dawn::Device::Acquire(nullAdapter.CreateDevice()); + + dawnProcTable procs = dawn_native::GetProcs(); dawnSetProcs(&procs); - device = dawn::Device::Acquire(cDevice); device.SetErrorCallback(ValidationTest::OnDeviceError, static_cast(reinterpret_cast(this))); } diff --git a/src/tests/unittests/validation/ValidationTest.h b/src/tests/unittests/validation/ValidationTest.h index c6bd9083cb..1e16baf6c6 100644 --- a/src/tests/unittests/validation/ValidationTest.h +++ b/src/tests/unittests/validation/ValidationTest.h @@ -19,6 +19,10 @@ #include "dawn/dawncpp.h" #include "dawn/dawncpp_traits.h" +namespace dawn_native { + class Instance; +}; + #define ASSERT_DEVICE_ERROR(statement) \ StartExpectDeviceError(); \ statement; \ @@ -66,6 +70,8 @@ class ValidationTest : public testing::Test { dawn::Device device; private: + std::unique_ptr mInstance; + static void OnDeviceError(const char* message, dawnCallbackUserdata userdata); std::string mDeviceErrorMessage; bool mExpectError = false;