d3d11: support MultiPlanarFormats and enable related tests

Bug: dawn:1724
Change-Id: Id2191c1ac8aeac5298736c888dd0fdc05b5ee581
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/136000
Commit-Queue: Peng Huang <penghuang@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
diff --git a/src/dawn/native/d3d11/DeviceInfoD3D11.cpp b/src/dawn/native/d3d11/DeviceInfoD3D11.cpp
index 02c6c3c..294466b 100644
--- a/src/dawn/native/d3d11/DeviceInfoD3D11.cpp
+++ b/src/dawn/native/d3d11/DeviceInfoD3D11.cpp
@@ -38,6 +38,17 @@
     info.shaderProfiles[SingleShaderStage::Fragment] = L"ps_5_0";
     info.shaderProfiles[SingleShaderStage::Compute] = L"cs_5_0";
 
+    // Runtime of the created texture (D3D11 device) and OpenSharedHandle runtime (Dawn's
+    // D3D12 device) must agree on resource sharing capability. For NV12 formats, D3D11
+    // requires at-least D3D11_SHARED_RESOURCE_TIER_2 support.
+    // https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_shared_resource_tier
+    D3D11_FEATURE_DATA_D3D11_OPTIONS5 featureOptions5{};
+    DAWN_TRY(CheckHRESULT(device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS5,
+                                                      &featureOptions5, sizeof(featureOptions5)),
+                          "D3D11_FEATURE_D3D11_OPTIONS5"));
+    info.supportsSharedResourceCapabilityTier2 =
+        featureOptions5.SharedResourceTier >= D3D11_SHARED_RESOURCE_TIER_2;
+
     return std::move(info);
 }
 
diff --git a/src/dawn/native/d3d11/DeviceInfoD3D11.h b/src/dawn/native/d3d11/DeviceInfoD3D11.h
index 71192f7..d0d155b 100644
--- a/src/dawn/native/d3d11/DeviceInfoD3D11.h
+++ b/src/dawn/native/d3d11/DeviceInfoD3D11.h
@@ -30,6 +30,7 @@
     // indicates that current driver supports the maximum shader model is shader model 6.2.
     uint32_t shaderModel;
     PerStage<std::wstring> shaderProfiles;
+    bool supportsSharedResourceCapabilityTier2;
 };
 
 ResultOrError<DeviceInfo> GatherDeviceInfo(const ComPtr<ID3D11Device>& device);
diff --git a/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp b/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp
index 1051649..a7fbf70 100644
--- a/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp
+++ b/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp
@@ -137,6 +137,11 @@
     EnableFeature(Feature::DepthClipControl);
     EnableFeature(Feature::TextureCompressionBC);
     EnableFeature(Feature::SurfaceCapabilities);
+
+    // To import multi planar textures, we need to at least tier 2 support.
+    if (mDeviceInfo.supportsSharedResourceCapabilityTier2) {
+        EnableFeature(Feature::MultiPlanarFormats);
+    }
 }
 
 MaybeError PhysicalDevice::InitializeSupportedLimitsImpl(CombinedLimits* limits) {
diff --git a/src/dawn/native/d3d11/TextureD3D11.cpp b/src/dawn/native/d3d11/TextureD3D11.cpp
index ece87ff..24f829f 100644
--- a/src/dawn/native/d3d11/TextureD3D11.cpp
+++ b/src/dawn/native/d3d11/TextureD3D11.cpp
@@ -101,8 +101,19 @@
 }
 
 MaybeError ValidateVideoTextureCanBeShared(Device* device, DXGI_FORMAT textureFormat) {
-    // TODO(dawn:1724): support video textures
-    return DAWN_UNIMPLEMENTED_ERROR("Video textures are not supported.");
+    const bool supportsSharedResourceCapabilityTier2 =
+        device->GetDeviceInfo().supportsSharedResourceCapabilityTier2;
+    switch (textureFormat) {
+        case DXGI_FORMAT_NV12:
+            if (supportsSharedResourceCapabilityTier2) {
+                return {};
+            }
+            break;
+        default:
+            break;
+    }
+
+    return DAWN_VALIDATION_ERROR("DXGI format does not support cross-API sharing.");
 }
 
 // static
diff --git a/src/dawn/tests/BUILD.gn b/src/dawn/tests/BUILD.gn
index dbdc587..01888d5 100644
--- a/src/dawn/tests/BUILD.gn
+++ b/src/dawn/tests/BUILD.gn
@@ -578,14 +578,14 @@
       "dxgi.lib",
     ]
 
-    sources += [ "end2end/D3DResourceWrappingTests.cpp" ]
+    sources += [
+      "end2end/D3DResourceWrappingTests.cpp",
+      "end2end/VideoViewsTests_win.cpp",
+    ]
   }
 
   if (dawn_enable_d3d12) {
-    sources += [
-      "end2end/D3D12CachingTests.cpp",
-      "end2end/VideoViewsTests_win.cpp",
-    ]
+    sources += [ "end2end/D3D12CachingTests.cpp" ]
   }
 
   if (dawn_enable_metal) {
@@ -604,8 +604,8 @@
     ]
   }
 
-  if (dawn_enable_d3d12 || (dawn_enable_vulkan && is_chromeos) ||
-      dawn_enable_metal) {
+  if (dawn_enable_d3d11 || dawn_enable_d3d12 ||
+      (dawn_enable_vulkan && is_chromeos) || dawn_enable_metal) {
     sources += [
       "end2end/VideoViewsTests.cpp",
       "end2end/VideoViewsTests.h",
diff --git a/src/dawn/tests/DawnTest.h b/src/dawn/tests/DawnTest.h
index 78cbf69..39b9f0c 100644
--- a/src/dawn/tests/DawnTest.h
+++ b/src/dawn/tests/DawnTest.h
@@ -725,6 +725,16 @@
 
 using DawnTest = DawnTestWithParams<>;
 
+// Instantiate the test once for all backends in the second param. Use it like this:
+//     DAWN_INSTANTIATE_TEST_V(MyTestFixture, std::vector<BackendTestConfig>({{MetalBackend},
+//     {OpenGLBackend}})
+#define DAWN_INSTANTIATE_TEST_V(testName, testParams)                                              \
+    INSTANTIATE_TEST_SUITE_P(, testName,                                                           \
+                             testing::ValuesIn(::detail::GetAvailableAdapterTestParamsForBackends( \
+                                 testParams.data(), testParams.size())),                           \
+                             DawnTestBase::PrintToStringParamName(#testName));                     \
+    GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(testName)
+
 // Instantiate the test once for each backend provided after the first argument. Use it like this:
 //     DAWN_INSTANTIATE_TEST(MyTestFixture, MetalBackend, OpenGLBackend)
 #define DAWN_INSTANTIATE_TEST(testName, ...)                                            \
diff --git a/src/dawn/tests/end2end/VideoViewsTests.cpp b/src/dawn/tests/end2end/VideoViewsTests.cpp
index 4af6bee..dc0e5b1 100644
--- a/src/dawn/tests/end2end/VideoViewsTests.cpp
+++ b/src/dawn/tests/end2end/VideoViewsTests.cpp
@@ -489,7 +489,7 @@
     mBackend->DestroyVideoTextureForTest(std::move(platformTexture));
 }
 
-DAWN_INSTANTIATE_TEST(VideoViewsTests, VideoViewsTestBackend::Backend());
+DAWN_INSTANTIATE_TEST_V(VideoViewsTests, VideoViewsTestBackend::Backends());
 
 }  // anonymous namespace
 }  // namespace dawn
diff --git a/src/dawn/tests/end2end/VideoViewsTests.h b/src/dawn/tests/end2end/VideoViewsTests.h
index 4b2175c..0e1b894 100644
--- a/src/dawn/tests/end2end/VideoViewsTests.h
+++ b/src/dawn/tests/end2end/VideoViewsTests.h
@@ -25,7 +25,7 @@
 
 class VideoViewsTestBackend {
   public:
-    static BackendTestConfig Backend();
+    static std::vector<BackendTestConfig> Backends();
     static std::unique_ptr<VideoViewsTestBackend> Create();
 
     virtual ~VideoViewsTestBackend();
diff --git a/src/dawn/tests/end2end/VideoViewsTests_gbm.cpp b/src/dawn/tests/end2end/VideoViewsTests_gbm.cpp
index ba7f1dd..eac747c 100644
--- a/src/dawn/tests/end2end/VideoViewsTests_gbm.cpp
+++ b/src/dawn/tests/end2end/VideoViewsTests_gbm.cpp
@@ -224,8 +224,8 @@
 }  // anonymous namespace
 
 // static
-BackendTestConfig VideoViewsTestBackend::Backend() {
-    return VulkanBackend();
+std::vector<BackendTestConfig> VideoViewsTestBackend::Backends() {
+    return {VulkanBackend()};
 }
 
 // static
diff --git a/src/dawn/tests/end2end/VideoViewsTests_mac.cpp b/src/dawn/tests/end2end/VideoViewsTests_mac.cpp
index 02c91fd..a6d1cf4 100644
--- a/src/dawn/tests/end2end/VideoViewsTests_mac.cpp
+++ b/src/dawn/tests/end2end/VideoViewsTests_mac.cpp
@@ -178,8 +178,8 @@
 }  // anonymous namespace
 
 // static
-BackendTestConfig VideoViewsTestBackend::Backend() {
-    return MetalBackend();
+std::vector<BackendTestConfig> VideoViewsTestBackend::Backends() {
+    return {MetalBackend()};
 }
 
 // static
diff --git a/src/dawn/tests/end2end/VideoViewsTests_win.cpp b/src/dawn/tests/end2end/VideoViewsTests_win.cpp
index f5b5e42..82040c6 100644
--- a/src/dawn/tests/end2end/VideoViewsTests_win.cpp
+++ b/src/dawn/tests/end2end/VideoViewsTests_win.cpp
@@ -202,8 +202,8 @@
 }  // anonymous namespace
 
 // static
-BackendTestConfig VideoViewsTestBackend::Backend() {
-    return D3D12Backend();
+std::vector<BackendTestConfig> VideoViewsTestBackend::Backends() {
+    return {D3D11Backend(), D3D12Backend()};
 }
 // static
 std::unique_ptr<VideoViewsTestBackend> VideoViewsTestBackend::Create() {