From 9978b2f7429279bb4b0f55b7fb271349a22d1dcb Mon Sep 17 00:00:00 2001 From: Austin Eng Date: Wed, 11 Aug 2021 14:27:55 +0000 Subject: [PATCH] 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 Reviewed-by: Brian Ho Commit-Queue: Austin Eng --- src/dawn_native/Adapter.h | 2 ++ src/dawn_native/DawnNative.cpp | 4 +++ src/dawn_native/d3d12/AdapterD3D12.cpp | 5 ++++ src/dawn_native/d3d12/AdapterD3D12.h | 3 ++ src/dawn_native/metal/BackendMTL.mm | 6 ++++ src/dawn_native/null/DeviceNull.cpp | 4 +++ src/dawn_native/null/DeviceNull.h | 3 ++ src/dawn_native/opengl/BackendGL.cpp | 6 ++++ src/dawn_native/vulkan/AdapterVk.cpp | 7 +++++ src/dawn_native/vulkan/AdapterVk.h | 3 ++ .../vulkan/external_memory/MemoryService.h | 3 ++ .../external_memory/MemoryServiceDmaBuf.cpp | 13 ++++---- .../external_memory/MemoryServiceNull.cpp | 5 ++++ .../external_memory/MemoryServiceOpaqueFD.cpp | 9 ++++-- .../MemoryServiceZirconHandle.cpp | 9 ++++-- .../external_semaphore/SemaphoreService.h | 4 +++ .../external_semaphore/SemaphoreServiceFD.cpp | 30 +++++++++++-------- .../SemaphoreServiceNull.cpp | 7 +++++ .../SemaphoreServiceZirconHandle.cpp | 30 +++++++++++-------- src/include/dawn_native/DawnNative.h | 4 +++ 20 files changed, 124 insertions(+), 33 deletions(-) diff --git a/src/dawn_native/Adapter.h b/src/dawn_native/Adapter.h index 118bcdfa67..7587eeb633 100644 --- a/src/dawn_native/Adapter.h +++ b/src/dawn_native/Adapter.h @@ -47,6 +47,8 @@ namespace dawn_native { const std::vector& requestedExtensions) const; WGPUDeviceProperties GetAdapterProperties() const; + virtual bool SupportsExternalImages() const = 0; + protected: PCIInfo mPCIInfo = {}; wgpu::AdapterType mAdapterType = wgpu::AdapterType::Unknown; diff --git a/src/dawn_native/DawnNative.cpp b/src/dawn_native/DawnNative.cpp index 849c6c0be6..1ac8d98d7a 100644 --- a/src/dawn_native/DawnNative.cpp +++ b/src/dawn_native/DawnNative.cpp @@ -103,6 +103,10 @@ namespace dawn_native { return mImpl->GetAdapterProperties(); } + bool Adapter::SupportsExternalImages() const { + return mImpl->SupportsExternalImages(); + } + Adapter::operator bool() const { return mImpl != nullptr; } diff --git a/src/dawn_native/d3d12/AdapterD3D12.cpp b/src/dawn_native/d3d12/AdapterD3D12.cpp index b43c1dae08..d26603a958 100644 --- a/src/dawn_native/d3d12/AdapterD3D12.cpp +++ b/src/dawn_native/d3d12/AdapterD3D12.cpp @@ -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; } diff --git a/src/dawn_native/d3d12/AdapterD3D12.h b/src/dawn_native/d3d12/AdapterD3D12.h index f41b3a1d37..ea6975efa4 100644 --- a/src/dawn_native/d3d12/AdapterD3D12.h +++ b/src/dawn_native/d3d12/AdapterD3D12.h @@ -30,6 +30,9 @@ namespace dawn_native { namespace d3d12 { Adapter(Backend* backend, ComPtr hardwareAdapter); ~Adapter() override; + // AdapterBase Implementation + bool SupportsExternalImages() const override; + const D3D12DeviceInfo& GetDeviceInfo() const; IDXGIAdapter3* GetHardwareAdapter() const; Backend* GetBackend() const; diff --git a/src/dawn_native/metal/BackendMTL.mm b/src/dawn_native/metal/BackendMTL.mm index 2029673fa1..a3a1212b94 100644 --- a/src/dawn_native/metal/BackendMTL.mm +++ b/src/dawn_native/metal/BackendMTL.mm @@ -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 CreateDeviceImpl(const DeviceDescriptor* descriptor) override { return Device::Create(this, mDevice, descriptor); diff --git a/src/dawn_native/null/DeviceNull.cpp b/src/dawn_native/null/DeviceNull.cpp index 6baad31e6a..0c0b0d3d2e 100644 --- a/src/dawn_native/null/DeviceNull.cpp +++ b/src/dawn_native/null/DeviceNull.cpp @@ -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& requiredExtensions) { mSupportedExtensions = GetInstance()->ExtensionNamesToExtensionsSet(requiredExtensions); diff --git a/src/dawn_native/null/DeviceNull.h b/src/dawn_native/null/DeviceNull.h index afa141f9be..0021056ccb 100644 --- a/src/dawn_native/null/DeviceNull.h +++ b/src/dawn_native/null/DeviceNull.h @@ -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& requiredExtensions); diff --git a/src/dawn_native/opengl/BackendGL.cpp b/src/dawn_native/opengl/BackendGL.cpp index 0f47e6c9d3..c2b24be1ff 100644 --- a/src/dawn_native/opengl/BackendGL.cpp +++ b/src/dawn_native/opengl/BackendGL.cpp @@ -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; diff --git a/src/dawn_native/vulkan/AdapterVk.cpp b/src/dawn_native/vulkan/AdapterVk.cpp index 194cc8264d..6d52f31615 100644 --- a/src/dawn_native/vulkan/AdapterVk.cpp +++ b/src/dawn_native/vulkan/AdapterVk.cpp @@ -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); diff --git a/src/dawn_native/vulkan/AdapterVk.h b/src/dawn_native/vulkan/AdapterVk.h index 94939d2572..a6141c42cc 100644 --- a/src/dawn_native/vulkan/AdapterVk.h +++ b/src/dawn_native/vulkan/AdapterVk.h @@ -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; diff --git a/src/dawn_native/vulkan/external_memory/MemoryService.h b/src/dawn_native/vulkan/external_memory/MemoryService.h index 0c4b64d49a..f0653f2c96 100644 --- a/src/dawn_native/vulkan/external_memory/MemoryService.h +++ b/src/dawn_native/vulkan/external_memory/MemoryService.h @@ -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, diff --git a/src/dawn_native/vulkan/external_memory/MemoryServiceDmaBuf.cpp b/src/dawn_native/vulkan/external_memory/MemoryServiceDmaBuf.cpp index d545890be5..d3611d9d8c 100644 --- a/src/dawn_native/vulkan/external_memory/MemoryServiceDmaBuf.cpp +++ b/src/dawn_native/vulkan/external_memory/MemoryServiceDmaBuf.cpp @@ -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, diff --git a/src/dawn_native/vulkan/external_memory/MemoryServiceNull.cpp b/src/dawn_native/vulkan/external_memory/MemoryServiceNull.cpp index 14d882a56a..1bb4f38dd2 100644 --- a/src/dawn_native/vulkan/external_memory/MemoryServiceNull.cpp +++ b/src/dawn_native/vulkan/external_memory/MemoryServiceNull.cpp @@ -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, diff --git a/src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp b/src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp index ebdab5b2fd..70db38b7b7 100644 --- a/src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp +++ b/src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp @@ -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, diff --git a/src/dawn_native/vulkan/external_memory/MemoryServiceZirconHandle.cpp b/src/dawn_native/vulkan/external_memory/MemoryServiceZirconHandle.cpp index ae8744f406..6dbfcf99a5 100644 --- a/src/dawn_native/vulkan/external_memory/MemoryServiceZirconHandle.cpp +++ b/src/dawn_native/vulkan/external_memory/MemoryServiceZirconHandle.cpp @@ -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, diff --git a/src/dawn_native/vulkan/external_semaphore/SemaphoreService.h b/src/dawn_native/vulkan/external_semaphore/SemaphoreService.h index cceaa2da5e..5eace87f7e 100644 --- a/src/dawn_native/vulkan/external_semaphore/SemaphoreService.h +++ b/src/dawn_native/vulkan/external_semaphore/SemaphoreService.h @@ -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(); diff --git a/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceFD.cpp b/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceFD.cpp index 6b228a9864..b25005645c 100644 --- a/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceFD.cpp +++ b/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceFD.cpp @@ -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; diff --git a/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceNull.cpp b/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceNull.cpp index aca4cb1268..3053029825 100644 --- a/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceNull.cpp +++ b/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceNull.cpp @@ -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; } diff --git a/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceZirconHandle.cpp b/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceZirconHandle.cpp index 20ffbad6d1..656b9fe835 100644 --- a/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceZirconHandle.cpp +++ b/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceZirconHandle.cpp @@ -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; diff --git a/src/include/dawn_native/DawnNative.h b/src/include/dawn_native/DawnNative.h index dd4d82c680..9baf128b08 100644 --- a/src/include/dawn_native/DawnNative.h +++ b/src/include/dawn_native/DawnNative.h @@ -109,6 +109,10 @@ namespace dawn_native { std::vector 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