Implement upstream RequestAdapter
Bug: dawn:160
Change-Id: Ifbce6f71fdf43a749c332bd691b63119929e0128
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/75640
Reviewed-by: Loko Kung <lokokung@google.com>
Commit-Queue: Austin Eng <enga@chromium.org>
diff --git a/src/common/Result.h b/src/common/Result.h
index 797f2d5..f913808 100644
--- a/src/common/Result.h
+++ b/src/common/Result.h
@@ -179,6 +179,8 @@
template <typename U>
Result(Ref<U>&& success);
+ template <typename U>
+ Result(const Ref<U>& success);
Result(std::unique_ptr<E> error);
template <typename U>
@@ -412,6 +414,11 @@
}
template <typename T, typename E>
+template <typename U>
+Result<Ref<T>, E>::Result(const Ref<U>& success) : Result(Ref<U>(success)) {
+}
+
+template <typename T, typename E>
Result<Ref<T>, E>::Result(std::unique_ptr<E> error)
: mPayload(detail::MakePayload(error.release(), detail::Error)) {
}
diff --git a/src/dawn_native/Adapter.cpp b/src/dawn_native/Adapter.cpp
index 7c09235..2c485e7 100644
--- a/src/dawn_native/Adapter.cpp
+++ b/src/dawn_native/Adapter.cpp
@@ -107,10 +107,15 @@
void AdapterBase::APIRequestDevice(const DeviceDescriptor* descriptor,
WGPURequestDeviceCallback callback,
void* userdata) {
+ static constexpr DeviceDescriptor kDefaultDescriptor = {};
+ if (descriptor == nullptr) {
+ descriptor = &kDefaultDescriptor;
+ }
auto result = CreateDeviceInternal(descriptor);
if (result.IsError()) {
std::unique_ptr<ErrorData> errorData = result.AcquireError();
+ // TODO(crbug.com/dawn/1122): Call callbacks only on wgpuInstanceProcessEvents
callback(WGPURequestDeviceStatus_Error, nullptr,
errorData->GetFormattedMessage().c_str(), userdata);
return;
@@ -120,6 +125,7 @@
WGPURequestDeviceStatus status =
device == nullptr ? WGPURequestDeviceStatus_Unknown : WGPURequestDeviceStatus_Success;
+ // TODO(crbug.com/dawn/1122): Call callbacks only on wgpuInstanceProcessEvents
callback(status, ToAPI(device.Detach()), nullptr, userdata);
}
diff --git a/src/dawn_native/BackendConnection.cpp b/src/dawn_native/BackendConnection.cpp
index a25010f..b0aae67 100644
--- a/src/dawn_native/BackendConnection.cpp
+++ b/src/dawn_native/BackendConnection.cpp
@@ -28,7 +28,7 @@
return mInstance;
}
- ResultOrError<std::vector<std::unique_ptr<AdapterBase>>> BackendConnection::DiscoverAdapters(
+ ResultOrError<std::vector<Ref<AdapterBase>>> BackendConnection::DiscoverAdapters(
const AdapterDiscoveryOptionsBase* options) {
return DAWN_FORMAT_VALIDATION_ERROR("DiscoverAdapters not implemented for this backend.");
}
diff --git a/src/dawn_native/BackendConnection.h b/src/dawn_native/BackendConnection.h
index e9007e3..5105142 100644
--- a/src/dawn_native/BackendConnection.h
+++ b/src/dawn_native/BackendConnection.h
@@ -34,10 +34,10 @@
// 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<std::unique_ptr<AdapterBase>> DiscoverDefaultAdapters() = 0;
+ virtual std::vector<Ref<AdapterBase>> DiscoverDefaultAdapters() = 0;
// Returns new adapters created with the backend-specific options.
- virtual ResultOrError<std::vector<std::unique_ptr<AdapterBase>>> DiscoverAdapters(
+ virtual ResultOrError<std::vector<Ref<AdapterBase>>> DiscoverAdapters(
const AdapterDiscoveryOptionsBase* options);
private:
diff --git a/src/dawn_native/DawnNative.cpp b/src/dawn_native/DawnNative.cpp
index 4079cd6..b166c44 100644
--- a/src/dawn_native/DawnNative.cpp
+++ b/src/dawn_native/DawnNative.cpp
@@ -76,14 +76,33 @@
Adapter::Adapter() = default;
Adapter::Adapter(AdapterBase* impl) : mImpl(impl) {
+ if (mImpl != nullptr) {
+ mImpl->Reference();
+ }
}
Adapter::~Adapter() {
+ if (mImpl != nullptr) {
+ mImpl->Release();
+ }
mImpl = nullptr;
}
- Adapter::Adapter(const Adapter& other) = default;
- Adapter& Adapter::operator=(const Adapter& other) = default;
+ Adapter::Adapter(const Adapter& other) : Adapter(other.mImpl) {
+ }
+
+ Adapter& Adapter::operator=(const Adapter& other) {
+ if (this != &other) {
+ if (mImpl) {
+ mImpl->Release();
+ }
+ mImpl = other.mImpl;
+ if (mImpl) {
+ mImpl->Reference();
+ }
+ }
+ return *this;
+ }
void Adapter::GetProperties(wgpu::AdapterProperties* properties) const {
GetProperties(reinterpret_cast<WGPUAdapterProperties*>(properties));
@@ -189,8 +208,8 @@
std::vector<Adapter> Instance::GetAdapters() const {
// Adapters are owned by mImpl so it is safe to return non RAII pointers to them
std::vector<Adapter> adapters;
- for (const std::unique_ptr<AdapterBase>& adapter : mImpl->GetAdapters()) {
- adapters.push_back({adapter.get()});
+ for (const Ref<AdapterBase>& adapter : mImpl->GetAdapters()) {
+ adapters.push_back({adapter.Get()});
}
return adapters;
}
diff --git a/src/dawn_native/Device.cpp b/src/dawn_native/Device.cpp
index a08bc06..559fa93 100644
--- a/src/dawn_native/Device.cpp
+++ b/src/dawn_native/Device.cpp
@@ -535,6 +535,7 @@
}
ErrorScope scope = mErrorScopeStack->Pop();
if (callback != nullptr) {
+ // TODO(crbug.com/dawn/1122): Call callbacks only on wgpuInstanceProcessEvents
callback(static_cast<WGPUErrorType>(scope.GetErrorType()), scope.GetErrorMessage(),
userdata);
}
@@ -973,6 +974,7 @@
// callback.
if (maybeResult.IsError()) {
std::unique_ptr<ErrorData> error = maybeResult.AcquireError();
+ // TODO(crbug.com/dawn/1122): Call callbacks only on wgpuInstanceProcessEvents
callback(WGPUCreatePipelineAsyncStatus_Error, nullptr, error->GetMessage().c_str(),
userdata);
}
@@ -1015,6 +1017,7 @@
// callback.
if (maybeResult.IsError()) {
std::unique_ptr<ErrorData> error = maybeResult.AcquireError();
+ // TODO(crbug.com/dawn/1122): Call callbacks only on wgpuInstanceProcessEvents
callback(WGPUCreatePipelineAsyncStatus_Error, nullptr, error->GetMessage().c_str(),
userdata);
}
@@ -1325,6 +1328,7 @@
Ref<ComputePipelineBase> cachedComputePipeline =
GetCachedComputePipeline(uninitializedComputePipeline.Get());
if (cachedComputePipeline.Get() != nullptr) {
+ // TODO(crbug.com/dawn/1122): Call callbacks only on wgpuInstanceProcessEvents
callback(WGPUCreatePipelineAsyncStatus_Success, ToAPI(cachedComputePipeline.Detach()),
"", userdata);
} else {
@@ -1471,6 +1475,7 @@
Ref<RenderPipelineBase> cachedRenderPipeline =
GetCachedRenderPipeline(uninitializedRenderPipeline.Get());
if (cachedRenderPipeline != nullptr) {
+ // TODO(crbug.com/dawn/1122): Call callbacks only on wgpuInstanceProcessEvents
callback(WGPUCreatePipelineAsyncStatus_Success, ToAPI(cachedRenderPipeline.Detach()),
"", userdata);
} else {
diff --git a/src/dawn_native/Instance.cpp b/src/dawn_native/Instance.cpp
index 12abde6..201487e 100644
--- a/src/dawn_native/Instance.cpp
+++ b/src/dawn_native/Instance.cpp
@@ -15,16 +15,24 @@
#include "dawn_native/Instance.h"
#include "common/Assert.h"
+#include "common/GPUInfo.h"
#include "common/Log.h"
#include "dawn_native/ErrorData.h"
#include "dawn_native/Surface.h"
#include "dawn_native/ValidationUtils_autogen.h"
#include "dawn_platform/DawnPlatform.h"
+// For SwiftShader fallback
+#if defined(DAWN_ENABLE_BACKEND_VULKAN)
+# include "dawn_native/VulkanBackend.h"
+#endif // defined(DAWN_ENABLE_BACKEND_VULKAN)
+
#if defined(DAWN_USE_X11)
# include "dawn_native/XlibXcbFunctions.h"
#endif // defined(DAWN_USE_X11)
+#include <optional>
+
namespace dawn::native {
// Forward definitions of each backend's "Connect" function that creates new BackendConnection.
@@ -102,7 +110,100 @@
void InstanceBase::APIRequestAdapter(const RequestAdapterOptions* options,
WGPURequestAdapterCallback callback,
void* userdata) {
- callback(WGPURequestAdapterStatus_Error, nullptr, "Not implemented", userdata);
+ static constexpr RequestAdapterOptions kDefaultOptions = {};
+ if (options == nullptr) {
+ options = &kDefaultOptions;
+ }
+ auto result = RequestAdapterInternal(options);
+ if (result.IsError()) {
+ auto err = result.AcquireError();
+ std::string msg = err->GetFormattedMessage();
+ // TODO(crbug.com/dawn/1122): Call callbacks only on wgpuInstanceProcessEvents
+ callback(WGPURequestAdapterStatus_Error, nullptr, msg.c_str(), userdata);
+ } else {
+ Ref<AdapterBase> adapter = result.AcquireSuccess();
+ // TODO(crbug.com/dawn/1122): Call callbacks only on wgpuInstanceProcessEvents
+ callback(WGPURequestAdapterStatus_Success, ToAPI(adapter.Detach()), nullptr, userdata);
+ }
+ }
+
+ ResultOrError<Ref<AdapterBase>> InstanceBase::RequestAdapterInternal(
+ const RequestAdapterOptions* options) {
+ ASSERT(options != nullptr);
+ if (options->forceFallbackAdapter) {
+#if defined(DAWN_ENABLE_BACKEND_VULKAN)
+ if (GetEnabledBackends()[wgpu::BackendType::Vulkan]) {
+ dawn_native::vulkan::AdapterDiscoveryOptions vulkanOptions;
+ vulkanOptions.forceSwiftShader = true;
+ DAWN_TRY(DiscoverAdaptersInternal(&vulkanOptions));
+ }
+#else
+ return Ref<AdapterBase>(nullptr);
+#endif // defined(DAWN_ENABLE_BACKEND_VULKAN)
+ } else {
+ DiscoverDefaultAdapters();
+ }
+
+ wgpu::AdapterType preferredType;
+ switch (options->powerPreference) {
+ case wgpu::PowerPreference::LowPower:
+ preferredType = wgpu::AdapterType::IntegratedGPU;
+ break;
+ case wgpu::PowerPreference::Undefined:
+ case wgpu::PowerPreference::HighPerformance:
+ preferredType = wgpu::AdapterType::DiscreteGPU;
+ break;
+ }
+
+ std::optional<size_t> discreteGPUAdapterIndex;
+ std::optional<size_t> integratedGPUAdapterIndex;
+ std::optional<size_t> cpuAdapterIndex;
+ std::optional<size_t> unknownAdapterIndex;
+
+ for (size_t i = 0; i < mAdapters.size(); ++i) {
+ AdapterProperties properties;
+ mAdapters[i]->APIGetProperties(&properties);
+
+ if (options->forceFallbackAdapter) {
+ if (!gpu_info::IsSwiftshader(properties.vendorID, properties.deviceID)) {
+ continue;
+ }
+ return mAdapters[i];
+ }
+ if (properties.adapterType == preferredType) {
+ return mAdapters[i];
+ }
+ switch (properties.adapterType) {
+ case wgpu::AdapterType::DiscreteGPU:
+ discreteGPUAdapterIndex = i;
+ break;
+ case wgpu::AdapterType::IntegratedGPU:
+ integratedGPUAdapterIndex = i;
+ break;
+ case wgpu::AdapterType::CPU:
+ cpuAdapterIndex = i;
+ break;
+ case wgpu::AdapterType::Unknown:
+ unknownAdapterIndex = i;
+ break;
+ }
+ }
+
+ // For now, we always prefer the discrete GPU
+ if (discreteGPUAdapterIndex) {
+ return mAdapters[*discreteGPUAdapterIndex];
+ }
+ if (integratedGPUAdapterIndex) {
+ return mAdapters[*integratedGPUAdapterIndex];
+ }
+ if (cpuAdapterIndex) {
+ return mAdapters[*cpuAdapterIndex];
+ }
+ if (unknownAdapterIndex) {
+ return mAdapters[*unknownAdapterIndex];
+ }
+
+ return Ref<AdapterBase>(nullptr);
}
void InstanceBase::DiscoverDefaultAdapters() {
@@ -116,10 +217,9 @@
// Query and merge all default adapters for all backends
for (std::unique_ptr<BackendConnection>& backend : mBackends) {
- std::vector<std::unique_ptr<AdapterBase>> backendAdapters =
- backend->DiscoverDefaultAdapters();
+ std::vector<Ref<AdapterBase>> backendAdapters = backend->DiscoverDefaultAdapters();
- for (std::unique_ptr<AdapterBase>& adapter : backendAdapters) {
+ for (Ref<AdapterBase>& adapter : backendAdapters) {
ASSERT(adapter->GetBackendType() == backend->GetType());
ASSERT(adapter->GetInstance() == this);
mAdapters.push_back(std::move(adapter));
@@ -146,7 +246,7 @@
return mFeaturesInfo.GetFeatureInfo(feature);
}
- const std::vector<std::unique_ptr<AdapterBase>>& InstanceBase::GetAdapters() const {
+ const std::vector<Ref<AdapterBase>>& InstanceBase::GetAdapters() const {
return mAdapters;
}
@@ -226,10 +326,10 @@
}
foundBackend = true;
- std::vector<std::unique_ptr<AdapterBase>> newAdapters;
+ std::vector<Ref<AdapterBase>> newAdapters;
DAWN_TRY_ASSIGN(newAdapters, backend->DiscoverAdapters(options));
- for (std::unique_ptr<AdapterBase>& adapter : newAdapters) {
+ for (Ref<AdapterBase>& adapter : newAdapters) {
ASSERT(adapter->GetBackendType() == backend->GetType());
ASSERT(adapter->GetInstance() == this);
mAdapters.push_back(std::move(adapter));
@@ -246,7 +346,6 @@
ASSERT(error != nullptr);
dawn::InfoLog() << error->GetFormattedMessage();
-
return true;
}
return false;
diff --git a/src/dawn_native/Instance.h b/src/dawn_native/Instance.h
index e7a72ca..913b2b6 100644
--- a/src/dawn_native/Instance.h
+++ b/src/dawn_native/Instance.h
@@ -52,7 +52,7 @@
void DiscoverDefaultAdapters();
bool DiscoverAdapters(const AdapterDiscoveryOptionsBase* options);
- const std::vector<std::unique_ptr<AdapterBase>>& GetAdapters() const;
+ const std::vector<Ref<AdapterBase>>& GetAdapters() const;
// Used to handle error that happen up to device creation.
bool ConsumedError(MaybeError maybeError);
@@ -96,6 +96,9 @@
MaybeError DiscoverAdaptersInternal(const AdapterDiscoveryOptionsBase* options);
+ ResultOrError<Ref<AdapterBase>> RequestAdapterInternal(
+ const RequestAdapterOptions* options);
+
BackendsBitset mBackendsConnected;
bool mDiscoveredDefaultAdapters = false;
@@ -107,7 +110,7 @@
std::unique_ptr<dawn::platform::Platform> mDefaultPlatform;
std::vector<std::unique_ptr<BackendConnection>> mBackends;
- std::vector<std::unique_ptr<AdapterBase>> mAdapters;
+ std::vector<Ref<AdapterBase>> mAdapters;
FeaturesInfo mFeaturesInfo;
TogglesInfo mTogglesInfo;
diff --git a/src/dawn_native/d3d12/BackendD3D12.cpp b/src/dawn_native/d3d12/BackendD3D12.cpp
index 8476553..cb29d69 100644
--- a/src/dawn_native/d3d12/BackendD3D12.cpp
+++ b/src/dawn_native/d3d12/BackendD3D12.cpp
@@ -66,13 +66,12 @@
return std::move(factory);
}
- ResultOrError<std::unique_ptr<AdapterBase>> CreateAdapterFromIDXGIAdapter(
+ ResultOrError<Ref<AdapterBase>> CreateAdapterFromIDXGIAdapter(
Backend* backend,
ComPtr<IDXGIAdapter> dxgiAdapter) {
ComPtr<IDXGIAdapter3> dxgiAdapter3;
DAWN_TRY(CheckHRESULT(dxgiAdapter.As(&dxgiAdapter3), "DXGIAdapter retrieval"));
- std::unique_ptr<Adapter> adapter =
- std::make_unique<Adapter>(backend, std::move(dxgiAdapter3));
+ Ref<Adapter> adapter = AcquireRef(new Adapter(backend, std::move(dxgiAdapter3)));
DAWN_TRY(adapter->Initialize());
return {std::move(adapter)};
@@ -150,7 +149,7 @@
return mFunctions.get();
}
- std::vector<std::unique_ptr<AdapterBase>> Backend::DiscoverDefaultAdapters() {
+ std::vector<Ref<AdapterBase>> Backend::DiscoverDefaultAdapters() {
AdapterDiscoveryOptions options;
auto result = DiscoverAdapters(&options);
if (result.IsError()) {
@@ -160,16 +159,16 @@
return result.AcquireSuccess();
}
- ResultOrError<std::vector<std::unique_ptr<AdapterBase>>> Backend::DiscoverAdapters(
+ ResultOrError<std::vector<Ref<AdapterBase>>> Backend::DiscoverAdapters(
const AdapterDiscoveryOptionsBase* optionsBase) {
ASSERT(optionsBase->backendType == WGPUBackendType_D3D12);
const AdapterDiscoveryOptions* options =
static_cast<const AdapterDiscoveryOptions*>(optionsBase);
- std::vector<std::unique_ptr<AdapterBase>> adapters;
+ std::vector<Ref<AdapterBase>> adapters;
if (options->dxgiAdapter != nullptr) {
// |dxgiAdapter| was provided. Discover just that adapter.
- std::unique_ptr<AdapterBase> adapter;
+ Ref<AdapterBase> adapter;
DAWN_TRY_ASSIGN(adapter, CreateAdapterFromIDXGIAdapter(this, options->dxgiAdapter));
adapters.push_back(std::move(adapter));
return std::move(adapters);
@@ -183,14 +182,14 @@
}
ASSERT(dxgiAdapter != nullptr);
- ResultOrError<std::unique_ptr<AdapterBase>> adapter =
+ ResultOrError<Ref<AdapterBase>> adapter =
CreateAdapterFromIDXGIAdapter(this, dxgiAdapter);
if (adapter.IsError()) {
GetInstance()->ConsumedError(adapter.AcquireError());
continue;
}
- adapters.push_back(std::move(adapter.AcquireSuccess()));
+ adapters.push_back(adapter.AcquireSuccess());
}
return adapters;
diff --git a/src/dawn_native/d3d12/BackendD3D12.h b/src/dawn_native/d3d12/BackendD3D12.h
index 8fb237d..ef339bf 100644
--- a/src/dawn_native/d3d12/BackendD3D12.h
+++ b/src/dawn_native/d3d12/BackendD3D12.h
@@ -40,8 +40,8 @@
const PlatformFunctions* GetFunctions() const;
- std::vector<std::unique_ptr<AdapterBase>> DiscoverDefaultAdapters() override;
- ResultOrError<std::vector<std::unique_ptr<AdapterBase>>> DiscoverAdapters(
+ std::vector<Ref<AdapterBase>> DiscoverDefaultAdapters() override;
+ ResultOrError<std::vector<Ref<AdapterBase>>> DiscoverAdapters(
const AdapterDiscoveryOptionsBase* optionsBase) override;
private:
diff --git a/src/dawn_native/metal/BackendMTL.h b/src/dawn_native/metal/BackendMTL.h
index da67335..26738f6 100644
--- a/src/dawn_native/metal/BackendMTL.h
+++ b/src/dawn_native/metal/BackendMTL.h
@@ -23,8 +23,8 @@
public:
Backend(InstanceBase* instance);
- std::vector<std::unique_ptr<AdapterBase>> DiscoverDefaultAdapters() override;
- ResultOrError<std::vector<std::unique_ptr<AdapterBase>>> DiscoverAdapters(
+ std::vector<Ref<AdapterBase>> DiscoverDefaultAdapters() override;
+ ResultOrError<std::vector<Ref<AdapterBase>>> DiscoverAdapters(
const AdapterDiscoveryOptionsBase* optionsBase) override;
};
diff --git a/src/dawn_native/metal/BackendMTL.mm b/src/dawn_native/metal/BackendMTL.mm
index bc9c6fc..5959e6b 100644
--- a/src/dawn_native/metal/BackendMTL.mm
+++ b/src/dawn_native/metal/BackendMTL.mm
@@ -558,7 +558,7 @@
}
}
- std::vector<std::unique_ptr<AdapterBase>> Backend::DiscoverDefaultAdapters() {
+ std::vector<Ref<AdapterBase>> Backend::DiscoverDefaultAdapters() {
AdapterDiscoveryOptions options;
auto result = DiscoverAdapters(&options);
if (result.IsError()) {
@@ -568,11 +568,11 @@
return result.AcquireSuccess();
}
- ResultOrError<std::vector<std::unique_ptr<AdapterBase>>> Backend::DiscoverAdapters(
+ ResultOrError<std::vector<Ref<AdapterBase>>> Backend::DiscoverAdapters(
const AdapterDiscoveryOptionsBase* optionsBase) {
ASSERT(optionsBase->backendType == WGPUBackendType_Metal);
- std::vector<std::unique_ptr<AdapterBase>> adapters;
+ std::vector<Ref<AdapterBase>> adapters;
BOOL supportedVersion = NO;
#if defined(DAWN_PLATFORM_MACOS)
if (@available(macOS 10.11, *)) {
@@ -581,7 +581,7 @@
NSRef<NSArray<id<MTLDevice>>> devices = AcquireNSRef(MTLCopyAllDevices());
for (id<MTLDevice> device in devices.Get()) {
- std::unique_ptr<Adapter> adapter = std::make_unique<Adapter>(GetInstance(), device);
+ Ref<Adapter> adapter = AcquireRef(new Adapter(GetInstance(), device));
if (!GetInstance()->ConsumedError(adapter->Initialize())) {
adapters.push_back(std::move(adapter));
}
@@ -593,8 +593,8 @@
if (@available(iOS 8.0, *)) {
supportedVersion = YES;
// iOS only has a single device so MTLCopyAllDevices doesn't exist there.
- std::unique_ptr<Adapter> adapter =
- std::make_unique<Adapter>(GetInstance(), MTLCreateSystemDefaultDevice());
+ Ref<Adapter> adapter =
+ AcquireRef(new Adapter(GetInstance(), MTLCreateSystemDefaultDevice()));
if (!GetInstance()->ConsumedError(adapter->Initialize())) {
adapters.push_back(std::move(adapter));
}
diff --git a/src/dawn_native/null/DeviceNull.cpp b/src/dawn_native/null/DeviceNull.cpp
index 3259f44..7aa1483 100644
--- a/src/dawn_native/null/DeviceNull.cpp
+++ b/src/dawn_native/null/DeviceNull.cpp
@@ -71,11 +71,11 @@
Backend(InstanceBase* instance) : BackendConnection(instance, wgpu::BackendType::Null) {
}
- std::vector<std::unique_ptr<AdapterBase>> DiscoverDefaultAdapters() override {
+ std::vector<Ref<AdapterBase>> DiscoverDefaultAdapters() override {
// There is always a single Null adapter because it is purely CPU based and doesn't
// depend on the system.
- std::vector<std::unique_ptr<AdapterBase>> adapters;
- std::unique_ptr<Adapter> adapter = std::make_unique<Adapter>(GetInstance());
+ std::vector<Ref<AdapterBase>> adapters;
+ Ref<Adapter> adapter = AcquireRef(new Adapter(GetInstance()));
adapters.push_back(std::move(adapter));
return adapters;
}
diff --git a/src/dawn_native/opengl/BackendGL.cpp b/src/dawn_native/opengl/BackendGL.cpp
index 2d5901e..982e84a 100644
--- a/src/dawn_native/opengl/BackendGL.cpp
+++ b/src/dawn_native/opengl/BackendGL.cpp
@@ -270,12 +270,12 @@
: BackendConnection(instance, backendType) {
}
- std::vector<std::unique_ptr<AdapterBase>> Backend::DiscoverDefaultAdapters() {
+ std::vector<Ref<AdapterBase>> Backend::DiscoverDefaultAdapters() {
// The OpenGL backend needs at least "getProcAddress" to discover an adapter.
return {};
}
- ResultOrError<std::vector<std::unique_ptr<AdapterBase>>> Backend::DiscoverAdapters(
+ ResultOrError<std::vector<Ref<AdapterBase>>> Backend::DiscoverAdapters(
const AdapterDiscoveryOptionsBase* optionsBase) {
// TODO(cwallez@chromium.org): For now only create a single OpenGL adapter because don't
// know how to handle MakeCurrent.
@@ -288,14 +288,13 @@
DAWN_INVALID_IF(options->getProc == nullptr,
"AdapterDiscoveryOptions::getProc must be set");
- std::unique_ptr<Adapter> adapter = std::make_unique<Adapter>(
- GetInstance(), static_cast<wgpu::BackendType>(optionsBase->backendType));
+ Ref<Adapter> adapter = AcquireRef(
+ new Adapter(GetInstance(), static_cast<wgpu::BackendType>(optionsBase->backendType)));
DAWN_TRY(adapter->InitializeGLFunctions(options->getProc));
DAWN_TRY(adapter->Initialize());
mCreatedAdapter = true;
- std::vector<std::unique_ptr<AdapterBase>> adapters;
- adapters.push_back(std::unique_ptr<AdapterBase>(adapter.release()));
+ std::vector<Ref<AdapterBase>> adapters{std::move(adapter)};
return std::move(adapters);
}
diff --git a/src/dawn_native/opengl/BackendGL.h b/src/dawn_native/opengl/BackendGL.h
index 9b925e4..2e38173 100644
--- a/src/dawn_native/opengl/BackendGL.h
+++ b/src/dawn_native/opengl/BackendGL.h
@@ -23,8 +23,8 @@
public:
Backend(InstanceBase* instance, wgpu::BackendType backendType);
- std::vector<std::unique_ptr<AdapterBase>> DiscoverDefaultAdapters() override;
- ResultOrError<std::vector<std::unique_ptr<AdapterBase>>> DiscoverAdapters(
+ std::vector<Ref<AdapterBase>> DiscoverDefaultAdapters() override;
+ ResultOrError<std::vector<Ref<AdapterBase>>> DiscoverAdapters(
const AdapterDiscoveryOptionsBase* options) override;
private:
diff --git a/src/dawn_native/vulkan/BackendVk.cpp b/src/dawn_native/vulkan/BackendVk.cpp
index 4378413..4916fe6 100644
--- a/src/dawn_native/vulkan/BackendVk.cpp
+++ b/src/dawn_native/vulkan/BackendVk.cpp
@@ -395,7 +395,7 @@
Backend::~Backend() = default;
- std::vector<std::unique_ptr<AdapterBase>> Backend::DiscoverDefaultAdapters() {
+ std::vector<Ref<AdapterBase>> Backend::DiscoverDefaultAdapters() {
AdapterDiscoveryOptions options;
auto result = DiscoverAdapters(&options);
if (result.IsError()) {
@@ -405,14 +405,14 @@
return result.AcquireSuccess();
}
- ResultOrError<std::vector<std::unique_ptr<AdapterBase>>> Backend::DiscoverAdapters(
+ ResultOrError<std::vector<Ref<AdapterBase>>> Backend::DiscoverAdapters(
const AdapterDiscoveryOptionsBase* optionsBase) {
ASSERT(optionsBase->backendType == WGPUBackendType_Vulkan);
const AdapterDiscoveryOptions* options =
static_cast<const AdapterDiscoveryOptions*>(optionsBase);
- std::vector<std::unique_ptr<AdapterBase>> adapters;
+ std::vector<Ref<AdapterBase>> adapters;
InstanceBase* instance = GetInstance();
for (ICD icd : kICDs) {
@@ -429,8 +429,8 @@
const std::vector<VkPhysicalDevice>& physicalDevices =
mVulkanInstances[icd]->GetPhysicalDevices();
for (uint32_t i = 0; i < physicalDevices.size(); ++i) {
- std::unique_ptr<Adapter> adapter = std::make_unique<Adapter>(
- instance, mVulkanInstances[icd].Get(), physicalDevices[i]);
+ Ref<Adapter> adapter = AcquireRef(
+ new Adapter(instance, mVulkanInstances[icd].Get(), physicalDevices[i]));
if (instance->ConsumedError(adapter->Initialize())) {
continue;
}
diff --git a/src/dawn_native/vulkan/BackendVk.h b/src/dawn_native/vulkan/BackendVk.h
index dd4a5da..3889401 100644
--- a/src/dawn_native/vulkan/BackendVk.h
+++ b/src/dawn_native/vulkan/BackendVk.h
@@ -73,8 +73,8 @@
MaybeError Initialize();
- std::vector<std::unique_ptr<AdapterBase>> DiscoverDefaultAdapters() override;
- ResultOrError<std::vector<std::unique_ptr<AdapterBase>>> DiscoverAdapters(
+ std::vector<Ref<AdapterBase>> DiscoverDefaultAdapters() override;
+ ResultOrError<std::vector<Ref<AdapterBase>>> DiscoverAdapters(
const AdapterDiscoveryOptionsBase* optionsBase) override;
private:
diff --git a/src/tests/end2end/AdapterDiscoveryTests.cpp b/src/tests/end2end/AdapterDiscoveryTests.cpp
index 8957ee4..e2841cf 100644
--- a/src/tests/end2end/AdapterDiscoveryTests.cpp
+++ b/src/tests/end2end/AdapterDiscoveryTests.cpp
@@ -13,10 +13,13 @@
// limitations under the License.
#include "common/GPUInfo.h"
+#include "common/Log.h"
#include "common/Platform.h"
#include "common/SystemUtils.h"
+#include "dawn/dawn_proc.h"
#include "dawn/webgpu_cpp.h"
#include "dawn_native/DawnNative.h"
+#include "tests/MockCallback.h"
#if defined(DAWN_ENABLE_BACKEND_VULKAN)
# include "dawn_native/VulkanBackend.h"
@@ -43,6 +46,8 @@
namespace {
+ using namespace testing;
+
class AdapterDiscoveryTests : public ::testing::Test {};
#if defined(DAWN_ENABLE_BACKEND_VULKAN)
@@ -266,4 +271,145 @@
}
#endif // defined(DAWN_ENABLE_BACKEND_VULKAN) && defined(DAWN_ENABLE_BACKEND_METAL)
+ class AdapterCreationTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ dawnProcSetProcs(&dawn_native::GetProcs());
+
+ {
+ auto nativeInstance = std::make_unique<dawn_native::Instance>();
+ nativeInstance->DiscoverDefaultAdapters();
+ for (dawn_native::Adapter& nativeAdapter : nativeInstance->GetAdapters()) {
+ anyAdapterAvailable = true;
+
+ wgpu::AdapterProperties properties;
+ nativeAdapter.GetProperties(&properties);
+ swiftShaderAvailable =
+ swiftShaderAvailable ||
+ gpu_info::IsSwiftshader(properties.vendorID, properties.deviceID);
+ discreteGPUAvailable = discreteGPUAvailable ||
+ properties.adapterType == wgpu::AdapterType::DiscreteGPU;
+ integratedGPUAvailable =
+ integratedGPUAvailable ||
+ properties.adapterType == wgpu::AdapterType::IntegratedGPU;
+ }
+ }
+
+ instance = wgpu::CreateInstance();
+ }
+
+ void TearDown() override {
+ instance = nullptr;
+ dawnProcSetProcs(nullptr);
+ }
+
+ wgpu::Instance instance;
+ bool anyAdapterAvailable = false;
+ bool swiftShaderAvailable = false;
+ bool discreteGPUAvailable = false;
+ bool integratedGPUAvailable = false;
+ };
+
+ // Test that requesting the default adapter works
+ TEST_F(AdapterCreationTest, DefaultAdapter) {
+ wgpu::RequestAdapterOptions options = {};
+
+ MockCallback<WGPURequestAdapterCallback> cb;
+
+ WGPUAdapter cAdapter = nullptr;
+ EXPECT_CALL(cb, Call(WGPURequestAdapterStatus_Success, _, nullptr, this))
+ .WillOnce(SaveArg<1>(&cAdapter));
+ instance.RequestAdapter(&options, cb.Callback(), cb.MakeUserdata(this));
+
+ wgpu::Adapter adapter = wgpu::Adapter::Acquire(cAdapter);
+ EXPECT_EQ(adapter != nullptr, anyAdapterAvailable);
+ }
+
+ // Test that passing nullptr for the options gets the default adapter
+ TEST_F(AdapterCreationTest, NullGivesDefaultAdapter) {
+ wgpu::RequestAdapterOptions options = {};
+
+ MockCallback<WGPURequestAdapterCallback> cb;
+
+ WGPUAdapter cAdapter = nullptr;
+ EXPECT_CALL(cb, Call(WGPURequestAdapterStatus_Success, _, nullptr, this))
+ .WillOnce(SaveArg<1>(&cAdapter));
+ instance.RequestAdapter(&options, cb.Callback(), cb.MakeUserdata(this));
+
+ wgpu::Adapter adapter = wgpu::Adapter::Acquire(cAdapter);
+ EXPECT_EQ(adapter != nullptr, anyAdapterAvailable);
+
+ EXPECT_CALL(cb, Call(WGPURequestAdapterStatus_Success, _, nullptr, this + 1))
+ .WillOnce(SaveArg<1>(&cAdapter));
+ instance.RequestAdapter(nullptr, cb.Callback(), cb.MakeUserdata(this + 1));
+
+ wgpu::Adapter adapter2 = wgpu::Adapter::Acquire(cAdapter);
+ EXPECT_EQ(adapter.Get(), adapter2.Get());
+ }
+
+ // Test that requesting the fallback adapter returns SwiftShader.
+ TEST_F(AdapterCreationTest, FallbackAdapter) {
+ wgpu::RequestAdapterOptions options = {};
+ options.forceFallbackAdapter = true;
+
+ MockCallback<WGPURequestAdapterCallback> cb;
+
+ WGPUAdapter cAdapter = nullptr;
+ EXPECT_CALL(cb, Call(WGPURequestAdapterStatus_Success, _, nullptr, this))
+ .WillOnce(SaveArg<1>(&cAdapter));
+ instance.RequestAdapter(&options, cb.Callback(), cb.MakeUserdata(this));
+
+ wgpu::Adapter adapter = wgpu::Adapter::Acquire(cAdapter);
+ EXPECT_EQ(adapter != nullptr, swiftShaderAvailable);
+ if (adapter != nullptr) {
+ wgpu::AdapterProperties properties;
+ adapter.GetProperties(&properties);
+
+ EXPECT_EQ(properties.adapterType, wgpu::AdapterType::CPU);
+ EXPECT_TRUE(gpu_info::IsSwiftshader(properties.vendorID, properties.deviceID));
+ }
+ }
+
+ // Test that requesting a high performance GPU works
+ TEST_F(AdapterCreationTest, PreferHighPerformance) {
+ wgpu::RequestAdapterOptions options = {};
+ options.powerPreference = wgpu::PowerPreference::HighPerformance;
+
+ MockCallback<WGPURequestAdapterCallback> cb;
+
+ WGPUAdapter cAdapter = nullptr;
+ EXPECT_CALL(cb, Call(WGPURequestAdapterStatus_Success, _, nullptr, this))
+ .WillOnce(SaveArg<1>(&cAdapter));
+ instance.RequestAdapter(&options, cb.Callback(), cb.MakeUserdata(this));
+
+ wgpu::Adapter adapter = wgpu::Adapter::Acquire(cAdapter);
+ EXPECT_EQ(adapter != nullptr, anyAdapterAvailable);
+ if (discreteGPUAvailable) {
+ wgpu::AdapterProperties properties;
+ adapter.GetProperties(&properties);
+ EXPECT_EQ(properties.adapterType, wgpu::AdapterType::DiscreteGPU);
+ }
+ }
+
+ // Test that requesting a low power GPU works
+ TEST_F(AdapterCreationTest, PreferLowPower) {
+ wgpu::RequestAdapterOptions options = {};
+ options.powerPreference = wgpu::PowerPreference::LowPower;
+
+ MockCallback<WGPURequestAdapterCallback> cb;
+
+ WGPUAdapter cAdapter = nullptr;
+ EXPECT_CALL(cb, Call(WGPURequestAdapterStatus_Success, _, nullptr, this))
+ .WillOnce(SaveArg<1>(&cAdapter));
+ instance.RequestAdapter(&options, cb.Callback(), cb.MakeUserdata(this));
+
+ wgpu::Adapter adapter = wgpu::Adapter::Acquire(cAdapter);
+ EXPECT_EQ(adapter != nullptr, anyAdapterAvailable);
+ if (integratedGPUAvailable) {
+ wgpu::AdapterProperties properties;
+ adapter.GetProperties(&properties);
+ EXPECT_EQ(properties.adapterType, wgpu::AdapterType::IntegratedGPU);
+ }
+ }
+
} // anonymous namespace
diff --git a/src/tests/unittests/native/DeviceCreationTests.cpp b/src/tests/unittests/native/DeviceCreationTests.cpp
index 1a8ddb6..3d67255 100644
--- a/src/tests/unittests/native/DeviceCreationTests.cpp
+++ b/src/tests/unittests/native/DeviceCreationTests.cpp
@@ -99,6 +99,21 @@
EXPECT_NE(device, nullptr);
}
+ // Test successful call to RequestDevice with a null descriptor
+ TEST_F(DeviceCreationTest, RequestDeviceNullDescriptorSuccess) {
+ WGPUDevice cDevice;
+ {
+ MockCallback<WGPURequestDeviceCallback> cb;
+ EXPECT_CALL(cb, Call(WGPURequestDeviceStatus_Success, NotNull(), nullptr, this))
+ .WillOnce(SaveArg<1>(&cDevice));
+
+ adapter.RequestDevice(nullptr, cb.Callback(), cb.MakeUserdata(this));
+ }
+
+ wgpu::Device device = wgpu::Device::Acquire(cDevice);
+ EXPECT_NE(device, nullptr);
+ }
+
// Test failing call to RequestDevice with invalid feature
TEST_F(DeviceCreationTest, RequestDeviceFailure) {
MockCallback<WGPURequestDeviceCallback> cb;