Add Adapter::SupportsExternalImages

This commit adds a getter so that Chromium can check whether an
Adapter would support external images. External images are
necessary to implement the WebGPU swapchain and interop with the
rest of the web platform. We should not expose adapters that
cannot interop with the canvas and other web platform primitives
until WebGPU gains options to request more "limited" adapters.

Bug: dawn:1056
Change-Id: Iff83ac26b0e92dccdd4e29c0d854d9276a4a37bc
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/61580
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Brian Ho <hob@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
This commit is contained in:
Austin Eng 2021-08-11 14:27:55 +00:00 committed by Dawn LUCI CQ
parent a6ddb0e116
commit 9978b2f742
20 changed files with 124 additions and 33 deletions

View File

@ -47,6 +47,8 @@ namespace dawn_native {
const std::vector<const char*>& requestedExtensions) const;
WGPUDeviceProperties GetAdapterProperties() const;
virtual bool SupportsExternalImages() const = 0;
protected:
PCIInfo mPCIInfo = {};
wgpu::AdapterType mAdapterType = wgpu::AdapterType::Unknown;

View File

@ -103,6 +103,10 @@ namespace dawn_native {
return mImpl->GetAdapterProperties();
}
bool Adapter::SupportsExternalImages() const {
return mImpl->SupportsExternalImages();
}
Adapter::operator bool() const {
return mImpl != nullptr;
}

View File

@ -36,6 +36,11 @@ namespace dawn_native { namespace d3d12 {
CleanUpDebugLayerFilters();
}
bool Adapter::SupportsExternalImages() const {
// Via dawn_native::d3d12::ExternalImageDXGI::Create
return true;
}
const D3D12DeviceInfo& Adapter::GetDeviceInfo() const {
return mDeviceInfo;
}

View File

@ -30,6 +30,9 @@ namespace dawn_native { namespace d3d12 {
Adapter(Backend* backend, ComPtr<IDXGIAdapter3> hardwareAdapter);
~Adapter() override;
// AdapterBase Implementation
bool SupportsExternalImages() const override;
const D3D12DeviceInfo& GetDeviceInfo() const;
IDXGIAdapter3* GetHardwareAdapter() const;
Backend* GetBackend() const;

View File

@ -205,6 +205,12 @@ namespace dawn_native { namespace metal {
InitializeSupportedExtensions();
}
// AdapterBase Implementation
bool SupportsExternalImages() const override {
// Via dawn_native::metal::WrapIOSurface
return true;
}
private:
ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) override {
return Device::Create(this, mDevice, descriptor);

View File

@ -34,6 +34,10 @@ namespace dawn_native { namespace null {
Adapter::~Adapter() = default;
bool Adapter::SupportsExternalImages() const {
return false;
}
// Used for the tests that intend to use an adapter without all extensions enabled.
void Adapter::SetSupportedExtensions(const std::vector<const char*>& requiredExtensions) {
mSupportedExtensions = GetInstance()->ExtensionNamesToExtensionsSet(requiredExtensions);

View File

@ -169,6 +169,9 @@ namespace dawn_native { namespace null {
Adapter(InstanceBase* instance);
~Adapter() override;
// AdapterBase Implementation
bool SupportsExternalImages() const override;
// Used for the tests that intend to use an adapter without all extensions enabled.
void SetSupportedExtensions(const std::vector<const char*>& requiredExtensions);

View File

@ -194,6 +194,12 @@ namespace dawn_native { namespace opengl {
~Adapter() override = default;
// AdapterBase Implementation
bool SupportsExternalImages() const override {
// Via dawn_native::opengl::WrapExternalEGLImage
return GetBackendType() == wgpu::BackendType::OpenGLES;
}
private:
OpenGLFunctions mFunctions;

View File

@ -251,6 +251,13 @@ namespace dawn_native { namespace vulkan {
return {};
}
bool Adapter::SupportsExternalImages() const {
// Via dawn_native::vulkan::WrapVulkanImage
return external_memory::Service::CheckSupport(mDeviceInfo) &&
external_semaphore::Service::CheckSupport(mDeviceInfo, mPhysicalDevice,
mBackend->GetFunctions());
}
void Adapter::InitializeSupportedExtensions() {
if (mDeviceInfo.features.textureCompressionBC == VK_TRUE) {
mSupportedExtensions.EnableExtension(Extension::TextureCompressionBC);

View File

@ -29,6 +29,9 @@ namespace dawn_native { namespace vulkan {
Adapter(Backend* backend, VkPhysicalDevice physicalDevice);
~Adapter() override = default;
// AdapterBase Implementation
bool SupportsExternalImages() const override;
const VulkanDeviceInfo& GetDeviceInfo() const;
VkPhysicalDevice GetPhysicalDevice() const;
Backend* GetBackend() const;

View File

@ -22,6 +22,7 @@
namespace dawn_native { namespace vulkan {
class Device;
struct VulkanDeviceInfo;
}} // namespace dawn_native::vulkan
namespace dawn_native { namespace vulkan { namespace external_memory {
@ -36,6 +37,8 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
explicit Service(Device* device);
~Service();
static bool CheckSupport(const VulkanDeviceInfo& deviceInfo);
// True if the device reports it supports importing external memory.
bool SupportsImportMemory(VkFormat format,
VkImageType type,

View File

@ -60,15 +60,18 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
} // anonymous namespace
Service::Service(Device* device) : mDevice(device) {
const VulkanDeviceInfo& deviceInfo = mDevice->GetDeviceInfo();
mSupported = deviceInfo.HasExt(DeviceExt::ExternalMemoryFD) &&
deviceInfo.HasExt(DeviceExt::ImageDrmFormatModifier);
Service::Service(Device* device)
: mDevice(device), mSupported(CheckSupport(device->GetDeviceInfo())) {
}
Service::~Service() = default;
// static
bool Service::CheckSupport(const VulkanDeviceInfo& deviceInfo) {
return deviceInfo.HasExt(DeviceExt::ExternalMemoryFD) &&
deviceInfo.HasExt(DeviceExt::ImageDrmFormatModifier);
}
bool Service::SupportsImportMemory(VkFormat format,
VkImageType type,
VkImageTiling tiling,

View File

@ -24,6 +24,11 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
Service::~Service() = default;
// static
bool Service::CheckSupport(const VulkanDeviceInfo& deviceInfo) {
return false;
}
bool Service::SupportsImportMemory(VkFormat format,
VkImageType type,
VkImageTiling tiling,

View File

@ -22,12 +22,17 @@
namespace dawn_native { namespace vulkan { namespace external_memory {
Service::Service(Device* device) : mDevice(device) {
mSupported = device->GetDeviceInfo().HasExt(DeviceExt::ExternalMemoryFD);
Service::Service(Device* device)
: mDevice(device), mSupported(CheckSupport(device->GetDeviceInfo())) {
}
Service::~Service() = default;
// static
bool Service::CheckSupport(const VulkanDeviceInfo& deviceInfo) {
return deviceInfo.HasExt(DeviceExt::ExternalMemoryFD);
}
bool Service::SupportsImportMemory(VkFormat format,
VkImageType type,
VkImageTiling tiling,

View File

@ -22,12 +22,17 @@
namespace dawn_native { namespace vulkan { namespace external_memory {
Service::Service(Device* device) : mDevice(device) {
mSupported = device->GetDeviceInfo().HasExt(DeviceExt::ExternalMemoryZirconHandle);
Service::Service(Device* device)
: mDevice(device), mSupported(CheckSupport(device->GetDeviceInfo())) {
}
Service::~Service() = default;
// static
bool Service::CheckSupport(const VulkanDeviceInfo& deviceInfo) {
return deviceInfo.HasExt(DeviceExt::ExternalMemoryZirconHandle);
}
bool Service::SupportsImportMemory(VkFormat format,
VkImageType type,
VkImageTiling tiling,

View File

@ -30,6 +30,10 @@ namespace dawn_native { namespace vulkan { namespace external_semaphore {
explicit Service(Device* device);
~Service();
static bool CheckSupport(const VulkanDeviceInfo& deviceInfo,
VkPhysicalDevice physicalDevice,
const VulkanFunctions& fn);
// True if the device reports it supports this feature
bool Supported();

View File

@ -27,12 +27,21 @@ static constexpr VkExternalSemaphoreHandleTypeFlagBits kHandleType =
namespace dawn_native { namespace vulkan { namespace external_semaphore {
Service::Service(Device* device) : mDevice(device) {
mSupported = device->GetDeviceInfo().HasExt(DeviceExt::ExternalSemaphoreFD);
Service::Service(Device* device)
: mDevice(device),
mSupported(CheckSupport(device->GetDeviceInfo(),
ToBackend(device->GetAdapter())->GetPhysicalDevice(),
device->fn)) {
}
// Early out before we try using extension functions
if (!mSupported) {
return;
Service::~Service() = default;
// static
bool Service::CheckSupport(const VulkanDeviceInfo& deviceInfo,
VkPhysicalDevice physicalDevice,
const VulkanFunctions& fn) {
if (!deviceInfo.HasExt(DeviceExt::ExternalSemaphoreFD)) {
return false;
}
VkPhysicalDeviceExternalSemaphoreInfoKHR semaphoreInfo;
@ -44,17 +53,14 @@ namespace dawn_native { namespace vulkan { namespace external_semaphore {
semaphoreProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR;
semaphoreProperties.pNext = nullptr;
mDevice->fn.GetPhysicalDeviceExternalSemaphoreProperties(
ToBackend(mDevice->GetAdapter())->GetPhysicalDevice(), &semaphoreInfo,
&semaphoreProperties);
fn.GetPhysicalDeviceExternalSemaphoreProperties(physicalDevice, &semaphoreInfo,
&semaphoreProperties);
VkFlags requiredFlags = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR |
VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR;
mSupported =
mSupported && IsSubset(requiredFlags, semaphoreProperties.externalSemaphoreFeatures);
}
Service::~Service() = default;
return IsSubset(requiredFlags, semaphoreProperties.externalSemaphoreFeatures);
}
bool Service::Supported() {
return mSupported;

View File

@ -24,6 +24,13 @@ namespace dawn_native { namespace vulkan { namespace external_semaphore {
Service::~Service() = default;
// static
bool Service::CheckSupport(const VulkanDeviceInfo& deviceInfo,
VkPhysicalDevice physicalDevice,
const VulkanFunctions& fn) {
return false;
}
bool Service::Supported() {
return false;
}

View File

@ -20,12 +20,21 @@
namespace dawn_native { namespace vulkan { namespace external_semaphore {
Service::Service(Device* device) : mDevice(device) {
mSupported = device->GetDeviceInfo().hasExt(DeviceExt::ExternalSemaphoreZirconHandle);
Service::Service(Device* device)
: mDevice(device),
mSupported(CheckSupport(device->GetDeviceInfo(),
ToBackend(device->GetAdapter())->GetPhysicalDevice(),
device->fn)) {
}
// Early out before we try using extension functions
if (!mSupported) {
return;
Service::~Service() = default;
// static
bool Service::CheckSupport(const VulkanDeviceInfo& deviceInfo,
VkPhysicalDevice physicalDevice,
const VulkanFunctions& fn) {
if (!deviceInfo.HasExt(DeviceExt::ExternalSemaphoreZirconHandle)) {
return false;
}
VkPhysicalDeviceExternalSemaphoreInfoKHR semaphoreInfo;
@ -37,17 +46,14 @@ namespace dawn_native { namespace vulkan { namespace external_semaphore {
semaphoreProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR;
semaphoreProperties.pNext = nullptr;
mDevice->fn.GetPhysicalDeviceExternalSemaphoreProperties(
ToBackend(mDevice->GetAdapter())->GetPhysicalDevice(), &semaphoreInfo,
&semaphoreProperties);
fn.GetPhysicalDeviceExternalSemaphoreProperties(physicalDevice, &semaphoreInfo,
&semaphoreProperties);
VkFlags requiredFlags = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR |
VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR;
mSupported =
mSupported && IsSubset(requiredFlags, semaphoreProperties.externalSemaphoreFeatures);
}
Service::~Service() = default;
return IsSubset(requiredFlags, semaphoreProperties.externalSemaphoreFeatures);
}
bool Service::Supported() {
return mSupported;

View File

@ -109,6 +109,10 @@ namespace dawn_native {
std::vector<const char*> GetSupportedExtensions() const;
WGPUDeviceProperties GetAdapterProperties() const;
// Check that the Adapter is able to support importing external images. This is necessary
// to implement the swapchain and interop APIs in Chromium.
bool SupportsExternalImages() const;
explicit operator bool() const;
// Create a device on this adapter, note that the interface will change to include at least