Add WinUI SwapChainPanel support

Change-Id: I0cd6fc9a56912095fb7ef3b8b2ecdd26c143f4f9
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/234055
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn/dawn.json b/src/dawn/dawn.json
index e1d9ed2..50861d5 100644
--- a/src/dawn/dawn.json
+++ b/src/dawn/dawn.json
@@ -3696,7 +3696,16 @@
             {"name": "core window", "type": "void", "annotation": "*"}
         ]
     },
-    "surface descriptor from windows swap chain panel": {
+    "surface descriptor from windows UWP swap chain panel": {
+        "category": "structure",
+        "chained": "in",
+        "chain roots": ["surface descriptor"],
+        "tags": ["dawn"],
+        "members": [
+            {"name": "swap chain panel", "type": "void", "annotation": "*"}
+        ]
+    },
+    "surface descriptor from windows WinUI swap chain panel": {
         "category": "structure",
         "chained": "in",
         "chain roots": ["surface descriptor"],
@@ -3763,7 +3772,7 @@
             {"value": 0, "name": "surface descriptor from windows core window", "tags": ["dawn"]},
             {"value": 1, "name": "external texture binding entry", "tags": ["dawn"]},
             {"value": 2, "name": "external texture binding layout", "tags": ["dawn"]},
-            {"value": 3, "name": "surface descriptor from windows swap chain panel", "tags": ["dawn"]},
+            {"value": 3, "name": "surface descriptor from windows UWP swap chain panel", "tags": ["dawn"]},
             {"value": 4, "name": "dawn texture internal usage descriptor", "tags": ["dawn"]},
             {"value": 5, "name": "dawn encoder internal usage descriptor", "tags": ["dawn"]},
             {"value": 6, "name": "dawn instance descriptor", "tags": ["dawn", "native"]},
@@ -3825,7 +3834,8 @@
             {"value": 61, "name": "shared fence EGL sync export info", "tags": ["dawn", "native"]},
             {"value": 62, "name": "dawn injected invalid s type", "tags": ["dawn"]},
             {"value": 63, "name": "dawn compilation message utf16", "tags": ["dawn", "emscripten"]},
-            {"value": 64, "name": "dawn fake buffer OOM for testing", "tags": ["dawn"]}
+            {"value": 64, "name": "dawn fake buffer OOM for testing", "tags": ["dawn"]},
+            {"value": 65, "name": "surface descriptor from windows WinUI swap chain panel", "tags": ["dawn"]}
         ]
     },
     "texture": {
diff --git a/src/dawn/dawn_wire.json b/src/dawn/dawn_wire.json
index 01d17e2..aeceb9b 100644
--- a/src/dawn/dawn_wire.json
+++ b/src/dawn/dawn_wire.json
@@ -221,7 +221,8 @@
         "client_side_structures": [
             "FutureWaitInfo",
             "SurfaceDescriptorFromWindowsCoreWindow",
-            "SurfaceDescriptorFromWindowsSwapChainPanel",
+            "SurfaceDescriptorFromWindowsUWPSwapChainPanel",
+            "SurfaceDescriptorFromWindowsWinUISwapChainPanel",
             "SurfaceSourceMetalLayer",
             "SurfaceSourceWindowsHWND",
             "SurfaceSourceXlibWindow",
diff --git a/src/dawn/native/Surface.cpp b/src/dawn/native/Surface.cpp
index 01d4c74..d0b30ae 100644
--- a/src/dawn/native/Surface.cpp
+++ b/src/dawn/native/Surface.cpp
@@ -76,8 +76,11 @@
         case Surface::Type::WindowsCoreWindow:
             s->Append("WindowsCoreWindow");
             break;
-        case Surface::Type::WindowsSwapChainPanel:
-            s->Append("WindowsSwapChainPanel");
+        case Surface::Type::WindowsUWPSwapChainPanel:
+            s->Append("WindowsUWPSwapChainPanel");
+            break;
+        case Surface::Type::WindowsWinUISwapChainPanel:
+            s->Append("WindowsWinUISwapChainPanel");
             break;
         case Surface::Type::XlibWindow:
             s->Append("XlibWindow");
@@ -104,7 +107,8 @@
         type, (descriptor.ValidateBranches<
                   Branch<SurfaceSourceAndroidNativeWindow>, Branch<SurfaceSourceMetalLayer>,
                   Branch<SurfaceSourceWindowsHWND>, Branch<SurfaceDescriptorFromWindowsCoreWindow>,
-                  Branch<SurfaceDescriptorFromWindowsSwapChainPanel>,
+                  Branch<SurfaceDescriptorFromWindowsUWPSwapChainPanel>,
+                  Branch<SurfaceDescriptorFromWindowsWinUISwapChainPanel>,
                   Branch<SurfaceSourceXlibWindow>, Branch<SurfaceSourceWaylandSurface>>()));
     switch (type) {
 #if DAWN_PLATFORM_IS(ANDROID)
@@ -145,8 +149,8 @@
                             "Invalid CoreWindow");
             return descriptor;
         }
-        case wgpu::SType::SurfaceDescriptorFromWindowsSwapChainPanel: {
-            auto* subDesc = descriptor.Get<SurfaceDescriptorFromWindowsSwapChainPanel>();
+        case wgpu::SType::SurfaceDescriptorFromWindowsUWPSwapChainPanel: {
+            auto* subDesc = descriptor.Get<SurfaceDescriptorFromWindowsUWPSwapChainPanel>();
             DAWN_ASSERT(subDesc != nullptr);
             // Validate the swapChainPanel by querying for ISwapChainPanel interface
             ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> swapChainPanel;
@@ -156,6 +160,15 @@
                             "Invalid SwapChainPanel");
             return descriptor;
         }
+        case wgpu::SType::SurfaceDescriptorFromWindowsWinUISwapChainPanel: {
+            auto* subDesc = descriptor.Get<SurfaceDescriptorFromWindowsWinUISwapChainPanel>();
+            DAWN_ASSERT(subDesc != nullptr);
+            // Unfortunately, checking whether this is a valid
+            // Microsoft.UI.Xaml.Controls.SwapChainPanel would require the WindowsAppSDK as a
+            // dependency, which is not trivial. So we'll only check for nullptr here.
+            DAWN_INVALID_IF(subDesc->swapChainPanel == nullptr, "SwapChainPanel is nullptr.");
+            return descriptor;
+        }
 #endif  // defined(DAWN_USE_WINDOWS_UI)
 #if defined(DAWN_USE_WAYLAND)
         case wgpu::SType::SurfaceSourceWaylandSurface: {
@@ -283,8 +296,9 @@
             .ValidateBranches<
                 Branch<SurfaceSourceAndroidNativeWindow>, Branch<SurfaceSourceMetalLayer>,
                 Branch<SurfaceSourceWindowsHWND>, Branch<SurfaceDescriptorFromWindowsCoreWindow>,
-                Branch<SurfaceDescriptorFromWindowsSwapChainPanel>, Branch<SurfaceSourceXlibWindow>,
-                Branch<SurfaceSourceWaylandSurface>>()
+                Branch<SurfaceDescriptorFromWindowsUWPSwapChainPanel>,
+                Branch<SurfaceDescriptorFromWindowsWinUISwapChainPanel>,
+                Branch<SurfaceSourceXlibWindow>, Branch<SurfaceSourceWaylandSurface>>()
             .AcquireSuccess();
     switch (type) {
         case wgpu::SType::SurfaceSourceAndroidNativeWindow: {
@@ -313,10 +327,16 @@
             mCoreWindow = static_cast<IUnknown*>(subDesc->coreWindow);
             break;
         }
-        case wgpu::SType::SurfaceDescriptorFromWindowsSwapChainPanel: {
-            auto* subDesc = descriptor.Get<SurfaceDescriptorFromWindowsSwapChainPanel>();
-            mType = Type::WindowsSwapChainPanel;
-            mSwapChainPanel = static_cast<IUnknown*>(subDesc->swapChainPanel);
+        case wgpu::SType::SurfaceDescriptorFromWindowsUWPSwapChainPanel: {
+            auto* subDesc = descriptor.Get<SurfaceDescriptorFromWindowsUWPSwapChainPanel>();
+            mType = Type::WindowsUWPSwapChainPanel;
+            mUWPSwapChainPanel = static_cast<IUnknown*>(subDesc->swapChainPanel);
+            break;
+        }
+        case wgpu::SType::SurfaceDescriptorFromWindowsWinUISwapChainPanel: {
+            auto* subDesc = descriptor.Get<SurfaceDescriptorFromWindowsWinUISwapChainPanel>();
+            mType = Type::WindowsWinUISwapChainPanel;
+            mWinUISwapChainPanel = static_cast<IUnknown*>(subDesc->swapChainPanel);
             break;
         }
 #endif  // defined(DAWN_USE_WINDOWS_UI)
@@ -406,11 +426,21 @@
 #endif
 }
 
-IUnknown* Surface::GetSwapChainPanel() const {
+IUnknown* Surface::GetUWPSwapChainPanel() const {
     DAWN_ASSERT(!IsError());
-    DAWN_ASSERT(mType == Type::WindowsSwapChainPanel);
+    DAWN_ASSERT(mType == Type::WindowsUWPSwapChainPanel);
 #if defined(DAWN_USE_WINDOWS_UI)
-    return mSwapChainPanel.Get();
+    return mUWPSwapChainPanel.Get();
+#else
+    return nullptr;
+#endif
+}
+
+IUnknown* Surface::GetWinUISwapChainPanel() const {
+    DAWN_ASSERT(!IsError());
+    DAWN_ASSERT(mType == Type::WindowsWinUISwapChainPanel);
+#if defined(DAWN_USE_WINDOWS_UI)
+    return mWinUISwapChainPanel.Get();
 #else
     return nullptr;
 #endif
diff --git a/src/dawn/native/Surface.h b/src/dawn/native/Surface.h
index eaabd5a..4b075b9 100644
--- a/src/dawn/native/Surface.h
+++ b/src/dawn/native/Surface.h
@@ -83,7 +83,8 @@
         WaylandSurface,
         WindowsHWND,
         WindowsCoreWindow,
-        WindowsSwapChainPanel,
+        WindowsUWPSwapChainPanel,
+        WindowsWinUISwapChainPanel,
         XlibWindow,
     };
     Type GetType() const;
@@ -107,8 +108,11 @@
     // Valid to call if the type is WindowsCoreWindow
     IUnknown* GetCoreWindow() const;
 
-    // Valid to call if the type is WindowsSwapChainPanel
-    IUnknown* GetSwapChainPanel() const;
+    // Valid to call if the type is WindowsUWPSwapChainPanel
+    IUnknown* GetUWPSwapChainPanel() const;
+
+    // Valid to call if the type is WindowsWinUISwapChainPanel
+    IUnknown* GetWinUISwapChainPanel() const;
 
     // Valid to call if the type is WindowsXlib
     void* GetXDisplay() const;
@@ -169,8 +173,11 @@
     // WindowsCoreWindow
     ComPtr<IUnknown> mCoreWindow;
 
-    // WindowsSwapChainPanel
-    ComPtr<IUnknown> mSwapChainPanel;
+    // WindowsUWPSwapChainPanel
+    ComPtr<IUnknown> mUWPSwapChainPanel;
+
+    // WindowsWinUISwapChainPanel
+    ComPtr<IUnknown> mWinUISwapChainPanel;
 #endif  // defined(DAWN_USE_WINDOWS_UI)
 
     // Xlib
diff --git a/src/dawn/native/d3d/SwapChainD3D.cpp b/src/dawn/native/d3d/SwapChainD3D.cpp
index eb9a69f..55a452d 100644
--- a/src/dawn/native/d3d/SwapChainD3D.cpp
+++ b/src/dawn/native/d3d/SwapChainD3D.cpp
@@ -101,6 +101,17 @@
     return dxgiUsage;
 }
 
+#if defined(DAWN_USE_WINDOWS_UI)
+// Interface from microsoft.ui.xaml.media.dxinterop.h
+MIDL_INTERFACE("63aad0b8-7c24-40ff-85a8-640d944cc325")
+IWinUISwapChainPanelNative : public IUnknown {
+  public:
+    virtual HRESULT STDMETHODCALLTYPE SetSwapChain(
+        /* [annotation][in] */
+        _In_ IDXGISwapChain * swapChain) = 0;
+};
+#endif  // defined(DAWN_USE_WINDOWS_UI)
+
 }  // namespace
 
 SwapChain::~SwapChain() = default;
@@ -109,7 +120,11 @@
 // nullptr. If it is not nullptr it means that it is the swapchain previously in use on the
 // surface and that we have a chance to reuse it's underlying IDXGISwapChain and "buffers".
 MaybeError SwapChain::Initialize(SwapChainBase* previousSwapChain) {
-    DAWN_ASSERT(GetSurface()->GetType() == Surface::Type::WindowsHWND);
+    Surface::Type surfaceType = GetSurface()->GetType();
+    DAWN_ASSERT(surfaceType == Surface::Type::WindowsHWND ||
+                surfaceType == Surface::Type::WindowsCoreWindow ||
+                surfaceType == Surface::Type::WindowsUWPSwapChainPanel ||
+                surfaceType == Surface::Type::WindowsWinUISwapChainPanel);
 
     // Precompute the configuration parameters we want for the DXGI swapchain.
     mConfig.bufferCount = PresentModeToBufferCount(GetPresentMode());
@@ -224,13 +239,26 @@
             break;
         }
 #if defined(DAWN_USE_WINDOWS_UI)
-        case Surface::Type::WindowsSwapChainPanel: {
+        case Surface::Type::WindowsUWPSwapChainPanel: {
             DAWN_TRY(CheckHRESULT(
                 factory2->CreateSwapChainForComposition(GetD3DDeviceForCreatingSwapChain(),
                                                         &swapChainDesc, nullptr, &swapChain1),
                 "Creating the IDXGISwapChain1"));
             ComPtr<ISwapChainPanelNative> swapChainPanelNative;
-            DAWN_TRY(CheckHRESULT(GetSurface()->GetSwapChainPanel()->QueryInterface(
+            DAWN_TRY(CheckHRESULT(GetSurface()->GetUWPSwapChainPanel()->QueryInterface(
+                                      IID_PPV_ARGS(&swapChainPanelNative)),
+                                  "Getting ISwapChainPanelNative"));
+            DAWN_TRY(CheckHRESULT(swapChainPanelNative->SetSwapChain(swapChain1.Get()),
+                                  "Setting SwapChain"));
+            break;
+        }
+        case Surface::Type::WindowsWinUISwapChainPanel: {
+            DAWN_TRY(CheckHRESULT(
+                factory2->CreateSwapChainForComposition(GetD3DDeviceForCreatingSwapChain(),
+                                                        &swapChainDesc, nullptr, &swapChain1),
+                "Creating the IDXGISwapChain1"));
+            ComPtr<IWinUISwapChainPanelNative> swapChainPanelNative;
+            DAWN_TRY(CheckHRESULT(GetSurface()->GetWinUISwapChainPanel()->QueryInterface(
                                       IID_PPV_ARGS(&swapChainPanelNative)),
                                   "Getting ISwapChainPanelNative"));
             DAWN_TRY(CheckHRESULT(swapChainPanelNative->SetSwapChain(swapChain1.Get()),
diff --git a/src/dawn/tests/white_box/EGLImageWrappingTests.cpp b/src/dawn/tests/white_box/EGLImageWrappingTests.cpp
index 2631e14..8dd7100 100644
--- a/src/dawn/tests/white_box/EGLImageWrappingTests.cpp
+++ b/src/dawn/tests/white_box/EGLImageWrappingTests.cpp
@@ -228,7 +228,7 @@
     DAWN_TEST_UNSUPPORTED_IF(UsesWire());
 
     wgpu::ChainedStruct chainedDescriptor;
-    chainedDescriptor.sType = wgpu::SType::SurfaceDescriptorFromWindowsSwapChainPanel;
+    chainedDescriptor.sType = wgpu::SType::SurfaceDescriptorFromWindowsUWPSwapChainPanel;
     descriptor.nextInChain = &chainedDescriptor;
 
     ScopedEGLImage image = CreateDefaultEGLImage();
diff --git a/src/dawn/tests/white_box/GLTextureWrappingTests.cpp b/src/dawn/tests/white_box/GLTextureWrappingTests.cpp
index 3154020..fb31458 100644
--- a/src/dawn/tests/white_box/GLTextureWrappingTests.cpp
+++ b/src/dawn/tests/white_box/GLTextureWrappingTests.cpp
@@ -179,7 +179,7 @@
 // Test an error occurs if an invalid sType is the nextInChain
 TEST_P(GLTextureValidationTests, InvalidTextureDescriptor) {
     wgpu::ChainedStruct chainedDescriptor;
-    chainedDescriptor.sType = wgpu::SType::SurfaceDescriptorFromWindowsSwapChainPanel;
+    chainedDescriptor.sType = wgpu::SType::SurfaceDescriptorFromWindowsUWPSwapChainPanel;
     descriptor.nextInChain = &chainedDescriptor;
 
     ScopedGLTexture glTexture = CreateDefaultGLTexture();
diff --git a/src/dawn/tests/white_box/VulkanImageWrappingTests.cpp b/src/dawn/tests/white_box/VulkanImageWrappingTests.cpp
index ffb0e52..b011061 100644
--- a/src/dawn/tests/white_box/VulkanImageWrappingTests.cpp
+++ b/src/dawn/tests/white_box/VulkanImageWrappingTests.cpp
@@ -219,7 +219,7 @@
 // Test an error occurs if an invalid sType is the nextInChain
 TEST_P(VulkanImageWrappingValidationTests, InvalidTextureDescriptor) {
     wgpu::ChainedStruct chainedDescriptor;
-    chainedDescriptor.sType = wgpu::SType::SurfaceDescriptorFromWindowsSwapChainPanel;
+    chainedDescriptor.sType = wgpu::SType::SurfaceDescriptorFromWindowsUWPSwapChainPanel;
     defaultDescriptor.nextInChain = &chainedDescriptor;
 
     ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapVulkanImage(device, &defaultDescriptor,