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>
This commit is contained in:
Austin Eng 2022-01-12 23:08:35 +00:00 committed by Dawn LUCI CQ
parent 11797b4b07
commit a78192741e
19 changed files with 352 additions and 54 deletions

View File

@ -179,6 +179,8 @@ class [[nodiscard]] Result<Ref<T>, E> {
template <typename U>
Result(Ref<U>&& success);
template <typename U>
Result(const Ref<U>& success);
Result(std::unique_ptr<E> error);
template <typename U>
@ -411,6 +413,11 @@ Result<Ref<T>, E>::Result(Ref<U>&& success)
static_assert(std::is_convertible<U*, T*>::value, "");
}
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)) {

View File

@ -107,10 +107,15 @@ namespace dawn::native {
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 @@ namespace dawn::native {
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);
}

View File

@ -28,7 +28,7 @@ namespace dawn::native {
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.");
}

View File

@ -34,10 +34,10 @@ namespace dawn::native {
// 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:

View File

@ -76,14 +76,33 @@ namespace dawn::native {
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 @@ namespace dawn::native {
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;
}

View File

@ -535,6 +535,7 @@ namespace dawn::native {
}
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 @@ namespace dawn::native {
// 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 @@ namespace dawn::native {
// 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 @@ namespace dawn::native {
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 @@ namespace dawn::native {
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 {

View File

@ -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 @@ namespace dawn::native {
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 @@ namespace dawn::native {
// 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 @@ namespace dawn::native {
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 @@ namespace dawn::native {
}
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 @@ namespace dawn::native {
ASSERT(error != nullptr);
dawn::InfoLog() << error->GetFormattedMessage();
return true;
}
return false;

View File

@ -52,7 +52,7 @@ namespace dawn::native {
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 @@ namespace dawn::native {
MaybeError DiscoverAdaptersInternal(const AdapterDiscoveryOptionsBase* options);
ResultOrError<Ref<AdapterBase>> RequestAdapterInternal(
const RequestAdapterOptions* options);
BackendsBitset mBackendsConnected;
bool mDiscoveredDefaultAdapters = false;
@ -107,7 +110,7 @@ namespace dawn::native {
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;

View File

@ -66,13 +66,12 @@ namespace dawn::native::d3d12 {
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 @@ namespace dawn::native::d3d12 {
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 @@ namespace dawn::native::d3d12 {
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 @@ namespace dawn::native::d3d12 {
}
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;

View File

@ -40,8 +40,8 @@ namespace dawn::native::d3d12 {
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:

View File

@ -23,8 +23,8 @@ namespace dawn::native::metal {
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;
};

View File

@ -558,7 +558,7 @@ namespace dawn::native::metal {
}
}
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 @@ namespace dawn::native::metal {
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 @@ namespace dawn::native::metal {
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 @@ namespace dawn::native::metal {
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));
}

View File

@ -71,11 +71,11 @@ namespace dawn::native::null {
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;
}

View File

@ -270,12 +270,12 @@ namespace dawn::native::opengl {
: 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 @@ namespace dawn::native::opengl {
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);
}

View File

@ -23,8 +23,8 @@ namespace dawn::native::opengl {
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:

View File

@ -395,7 +395,7 @@ namespace dawn::native::vulkan {
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 @@ namespace dawn::native::vulkan {
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 @@ namespace dawn::native::vulkan {
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;
}

View File

@ -73,8 +73,8 @@ namespace dawn::native::vulkan {
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:

View File

@ -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 @@ namespace {
}
#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

View File

@ -99,6 +99,21 @@ namespace {
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;