Add FeatureLevel to AdapterBase; implement Compat.

This introduces the notion of FeatureLevel, currently consisting of
Core or Compatibility. Each AdapterBase is now constructed with the
FeatureLevel it supports.

When discovering PhysicalDevices, create an AdapterBase for each of
the FeaturLevels which that PhysicalDevice supports. For most of the
backends, this will mean Core and Compatibility, while OpenGL and
D3D11 support only Compatibility.

Bug: dawn:1796.

Change-Id: I828247ef43e2220805ccf6c08827aa5e2382a026
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/118240
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Stephen White <senorblanco@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Stephen White <senorblanco@chromium.org>
This commit is contained in:
Stephen White 2023-05-06 01:26:25 +00:00 committed by Dawn LUCI CQ
parent 3ee4f6af41
commit b9e12716c6
20 changed files with 118 additions and 13 deletions

View File

@ -53,7 +53,8 @@
"members": [
{"name": "compatible surface", "type": "surface", "optional": true},
{"name": "power preference", "type": "power preference", "default": "undefined"},
{"name": "force fallback adapter", "type": "bool", "default": "false"}
{"name": "force fallback adapter", "type": "bool", "default": "false"},
{"name": "compatibility mode", "type": "bool", "default": "false"}
]
},
"request adapter status": {
@ -140,7 +141,8 @@
{"name": "name", "type": "char", "annotation": "const*", "length": "strlen"},
{"name": "driver description", "type": "char", "annotation": "const*", "length": "strlen"},
{"name": "adapter type", "type": "adapter type"},
{"name": "backend type", "type": "backend type"}
{"name": "backend type", "type": "backend type"},
{"name": "compatibility mode", "type": "bool", "default": "false"}
]
},
"adapter type": {

View File

@ -20,8 +20,10 @@
namespace dawn::native {
AdapterBase::AdapterBase(const Ref<PhysicalDeviceBase>& physicalDevice)
: mPhysicalDevice(std::move(physicalDevice)) {}
AdapterBase::AdapterBase(const Ref<PhysicalDeviceBase>& physicalDevice, FeatureLevel featureLevel)
: mPhysicalDevice(std::move(physicalDevice)), mFeatureLevel(featureLevel) {
ASSERT(physicalDevice->SupportsFeatureLevel(featureLevel));
}
AdapterBase::~AdapterBase() = default;
@ -39,6 +41,7 @@ bool AdapterBase::APIGetLimits(SupportedLimits* limits) const {
void AdapterBase::APIGetProperties(AdapterProperties* properties) const {
mPhysicalDevice->APIGetProperties(properties);
properties->compatibilityMode = mFeatureLevel == FeatureLevel::Compatibility;
}
bool AdapterBase::APIHasFeature(wgpu::FeatureName feature) const {
@ -68,4 +71,8 @@ bool AdapterBase::AllowUnsafeAPIs() const {
!GetTogglesState().IsEnabled(Toggle::DisallowUnsafeAPIs);
}
FeatureLevel AdapterBase::GetFeatureLevel() const {
return mFeatureLevel;
}
} // namespace dawn::native

View File

@ -18,6 +18,7 @@
#include "dawn/native/DawnNative.h"
#include "dawn/common/RefCounted.h"
#include "dawn/native/PhysicalDevice.h"
#include "dawn/native/dawn_platform.h"
namespace dawn::native {
@ -28,7 +29,7 @@ struct SupportedLimits;
class AdapterBase : public RefCounted {
public:
explicit AdapterBase(const Ref<PhysicalDeviceBase>& physicalDevice);
AdapterBase(const Ref<PhysicalDeviceBase>& physicalDevice, FeatureLevel featureLevel);
~AdapterBase() override;
// WebGPU API
@ -53,8 +54,11 @@ class AdapterBase : public RefCounted {
// TODO(dawn:1685): Remove wrapper once DisallowUnsafeAPIs is fully removed.
bool AllowUnsafeAPIs() const;
FeatureLevel GetFeatureLevel() const;
private:
Ref<PhysicalDeviceBase> mPhysicalDevice;
FeatureLevel mFeatureLevel;
};
} // namespace dawn::native

View File

@ -255,6 +255,10 @@ ResultOrError<Ref<AdapterBase>> InstanceBase::RequestAdapterInternal(
AdapterProperties properties;
mAdapters[i]->APIGetProperties(&properties);
bool isCompatibility = mAdapters[i]->GetFeatureLevel() == FeatureLevel::Compatibility;
if (options->compatibilityMode != isCompatibility) {
continue;
}
if (options->forceFallbackAdapter) {
if (!gpu_info::IsGoogleSwiftshader(properties.vendorID, properties.deviceID)) {
continue;
@ -320,7 +324,12 @@ void InstanceBase::DiscoverDefaultAdapters() {
for (Ref<PhysicalDeviceBase>& physicalDevice : physicalDevices) {
ASSERT(physicalDevice->GetBackendType() == backend->GetType());
ASSERT(physicalDevice->GetInstance() == this);
mAdapters.push_back(AcquireRef(new AdapterBase(std::move(physicalDevice))));
for (auto featureLevel : {FeatureLevel::Compatibility, FeatureLevel::Core}) {
if (physicalDevice->SupportsFeatureLevel(featureLevel)) {
mAdapters.push_back(
AcquireRef(new AdapterBase(std::move(physicalDevice), featureLevel)));
}
}
}
}
@ -454,7 +463,12 @@ MaybeError InstanceBase::DiscoverAdaptersInternal(const AdapterDiscoveryOptionsB
for (Ref<PhysicalDeviceBase>& physicalDevice : newPhysicalDevices) {
ASSERT(physicalDevice->GetBackendType() == backend->GetType());
ASSERT(physicalDevice->GetInstance() == this);
mAdapters.push_back(AcquireRef(new AdapterBase(std::move(physicalDevice))));
for (auto featureLevel : {FeatureLevel::Compatibility, FeatureLevel::Core}) {
if (physicalDevice->SupportsFeatureLevel(featureLevel)) {
mAdapters.push_back(
AcquireRef(new AdapterBase(std::move(physicalDevice), featureLevel)));
}
}
}
}

View File

@ -33,6 +33,8 @@ namespace dawn::native {
class DeviceBase;
enum class FeatureLevel { Compatibility, Core };
class PhysicalDeviceBase : public RefCounted {
public:
PhysicalDeviceBase(InstanceBase* instance,
@ -78,6 +80,8 @@ class PhysicalDeviceBase : public RefCounted {
virtual bool SupportsExternalImages() const = 0;
virtual bool SupportsFeatureLevel(FeatureLevel featureLevel) const = 0;
protected:
uint32_t mVendorId = 0xFFFFFFFF;
std::string mVendorName;

View File

@ -73,6 +73,10 @@ bool PhysicalDevice::SupportsExternalImages() const {
return false;
}
bool PhysicalDevice::SupportsFeatureLevel(FeatureLevel featureLevel) const {
return featureLevel == FeatureLevel::Compatibility;
}
const DeviceInfo& PhysicalDevice::GetDeviceInfo() const {
return mDeviceInfo;
}

View File

@ -34,6 +34,8 @@ class PhysicalDevice : public d3d::PhysicalDevice {
// PhysicalDeviceBase Implementation
bool SupportsExternalImages() const override;
bool SupportsFeatureLevel(FeatureLevel featureLevel) const override;
const DeviceInfo& GetDeviceInfo() const;
ResultOrError<ComPtr<ID3D11Device>> CreateD3D11Device();

View File

@ -43,6 +43,10 @@ bool PhysicalDevice::SupportsExternalImages() const {
return true;
}
bool PhysicalDevice::SupportsFeatureLevel(FeatureLevel) const {
return true;
}
const D3D12DeviceInfo& PhysicalDevice::GetDeviceInfo() const {
return mDeviceInfo;
}

View File

@ -34,6 +34,7 @@ class PhysicalDevice : public d3d::PhysicalDevice {
// PhysicalDeviceBase Implementation
bool SupportsExternalImages() const override;
bool SupportsFeatureLevel(FeatureLevel featureLevel) const override;
const D3D12DeviceInfo& GetDeviceInfo() const;
Backend* GetBackend() const;

View File

@ -292,6 +292,8 @@ class PhysicalDevice : public PhysicalDeviceBase {
return true;
}
bool SupportsFeatureLevel(FeatureLevel) const override { return true; }
private:
ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(AdapterBase* adapter,
const DeviceDescriptor* descriptor,

View File

@ -51,6 +51,10 @@ bool PhysicalDevice::SupportsExternalImages() const {
return false;
}
bool PhysicalDevice::SupportsFeatureLevel(FeatureLevel) const {
return true;
}
MaybeError PhysicalDevice::InitializeImpl() {
return {};
}

View File

@ -181,6 +181,8 @@ class PhysicalDevice : public PhysicalDeviceBase {
// PhysicalDeviceBase Implementation
bool SupportsExternalImages() const override;
bool SupportsFeatureLevel(FeatureLevel featureLevel) const override;
// Used for the tests that intend to use an adapter without all features enabled.
using PhysicalDeviceBase::SetSupportedFeaturesForTesting;

View File

@ -227,6 +227,10 @@ ResultOrError<Ref<DeviceBase>> PhysicalDevice::CreateDeviceImpl(AdapterBase* ada
return Device::Create(adapter, descriptor, mFunctions, std::move(context), deviceToggles);
}
bool PhysicalDevice::SupportsFeatureLevel(FeatureLevel featureLevel) const {
return featureLevel == FeatureLevel::Compatibility;
}
MaybeError PhysicalDevice::ValidateFeatureSupportedWithTogglesImpl(
wgpu::FeatureName feature,
const TogglesState& toggles) const {

View File

@ -33,6 +33,7 @@ class PhysicalDevice : public PhysicalDeviceBase {
// PhysicalDeviceBase Implementation
bool SupportsExternalImages() const override;
bool SupportsFeatureLevel(FeatureLevel featureLevel) const override;
private:
MaybeError InitializeImpl() override;

View File

@ -429,6 +429,10 @@ bool PhysicalDevice::SupportsExternalImages() const {
mVulkanInstance->GetFunctions());
}
bool PhysicalDevice::SupportsFeatureLevel(FeatureLevel) const {
return true;
}
void PhysicalDevice::SetupBackendDeviceToggles(TogglesState* deviceToggles) const {
// TODO(crbug.com/dawn/857): tighten this workaround when this issue is fixed in both
// Vulkan SPEC and drivers.

View File

@ -35,6 +35,7 @@ class PhysicalDevice : public PhysicalDeviceBase {
// PhysicalDeviceBase Implementation
bool SupportsExternalImages() const override;
bool SupportsFeatureLevel(FeatureLevel featureLevel) const override;
const VulkanDeviceInfo& GetDeviceInfo() const;
VkPhysicalDevice GetVkPhysicalDevice() const;

View File

@ -65,7 +65,7 @@ TEST(AdapterDiscoveryTests, OnlySwiftShader) {
instance.DiscoverAdapters(&options);
const auto& adapters = instance.GetAdapters();
EXPECT_LE(adapters.size(), 1u); // 0 or 1 SwiftShader adapters.
EXPECT_LE(adapters.size(), 2u); // 0 or 2 SwiftShader adapters.
for (const auto& adapter : adapters) {
wgpu::AdapterProperties properties;
adapter.GetProperties(&properties);
@ -260,6 +260,9 @@ class AdapterCreationTest : public ::testing::Test {
wgpu::AdapterProperties properties;
nativeAdapter.GetProperties(&properties);
if (properties.compatibilityMode) {
continue;
}
swiftShaderAvailable =
swiftShaderAvailable ||
gpu_info::IsGoogleSwiftshader(properties.vendorID, properties.deviceID);
@ -387,6 +390,45 @@ TEST_F(AdapterCreationTest, PreferLowPower) {
}
}
// Test that requesting a Compatibility adapter is supported.
TEST_F(AdapterCreationTest, Compatibility) {
wgpu::RequestAdapterOptions options = {};
options.compatibilityMode = 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, anyAdapterAvailable);
wgpu::AdapterProperties properties;
adapter.GetProperties(&properties);
EXPECT_TRUE(properties.compatibilityMode);
}
// Test that requesting a Non-Compatibility adapter is supported and is default.
TEST_F(AdapterCreationTest, NonCompatibility) {
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);
wgpu::AdapterProperties properties;
adapter.GetProperties(&properties);
EXPECT_FALSE(properties.compatibilityMode);
}
// Test that GetInstance() returns the correct Instance.
TEST_F(AdapterCreationTest, GetInstance) {
wgpu::RequestAdapterOptions options = {};

View File

@ -34,9 +34,10 @@ class FeatureTests : public testing::Test {
mInstanceBase.Get(),
dawn::native::TogglesState(dawn::native::ToggleStage::Adapter)
.SetForTesting(dawn::native::Toggle::AllowUnsafeAPIs, true, true)),
mAdapterBase(&mPhysicalDevice),
mUnsafeAdapterBaseDisallow(&mUnsafePhysicalDeviceDisallow),
mUnsafeAdapterBase(&mUnsafePhysicalDevice) {}
mAdapterBase(&mPhysicalDevice, dawn::native::FeatureLevel::Core),
mUnsafeAdapterBaseDisallow(&mUnsafePhysicalDeviceDisallow,
dawn::native::FeatureLevel::Core),
mUnsafeAdapterBase(&mUnsafePhysicalDevice, dawn::native::FeatureLevel::Core) {}
std::vector<wgpu::FeatureName> GetAllFeatureNames() {
std::vector<wgpu::FeatureName> allFeatureNames(kTotalFeaturesCount);

View File

@ -56,7 +56,8 @@ class GetProcAddressTests : public testing::TestWithParam<DawnFlavor> {
GetProcAddressTests()
: testing::TestWithParam<DawnFlavor>(),
mNativeInstance(dawn::native::InstanceBase::Create()),
mAdapterBase(AcquireRef(new dawn::native::null::PhysicalDevice(mNativeInstance.Get()))) {}
mAdapterBase(AcquireRef(new dawn::native::null::PhysicalDevice(mNativeInstance.Get())),
dawn::native::FeatureLevel::Core) {}
void SetUp() override {
switch (GetParam()) {

View File

@ -27,7 +27,8 @@ class PerThreadProcTests : public testing::Test {
public:
PerThreadProcTests()
: mNativeInstance(dawn::native::InstanceBase::Create()),
mAdapterBase(AcquireRef(new dawn::native::null::PhysicalDevice(mNativeInstance.Get()))) {}
mAdapterBase(AcquireRef(new dawn::native::null::PhysicalDevice(mNativeInstance.Get())),
dawn::native::FeatureLevel::Core) {}
~PerThreadProcTests() override = default;
protected: