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; const std::vector<const char*>& requestedExtensions) const;
WGPUDeviceProperties GetAdapterProperties() const; WGPUDeviceProperties GetAdapterProperties() const;
virtual bool SupportsExternalImages() const = 0;
protected: protected:
PCIInfo mPCIInfo = {}; PCIInfo mPCIInfo = {};
wgpu::AdapterType mAdapterType = wgpu::AdapterType::Unknown; wgpu::AdapterType mAdapterType = wgpu::AdapterType::Unknown;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -251,6 +251,13 @@ namespace dawn_native { namespace vulkan {
return {}; 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() { void Adapter::InitializeSupportedExtensions() {
if (mDeviceInfo.features.textureCompressionBC == VK_TRUE) { if (mDeviceInfo.features.textureCompressionBC == VK_TRUE) {
mSupportedExtensions.EnableExtension(Extension::TextureCompressionBC); mSupportedExtensions.EnableExtension(Extension::TextureCompressionBC);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -109,6 +109,10 @@ namespace dawn_native {
std::vector<const char*> GetSupportedExtensions() const; std::vector<const char*> GetSupportedExtensions() const;
WGPUDeviceProperties GetAdapterProperties() 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; explicit operator bool() const;
// Create a device on this adapter, note that the interface will change to include at least // Create a device on this adapter, note that the interface will change to include at least