D3D11: Add an option to skip fence signal when accessing a STM.

Add a new option to SharedTextureMemoryD3D11Texture2DDescriptor to skip
fence signaling when STM's texture is accessed in a command buffer.

This would typically be used when the texture is shared between ANGLE &
Dawn which share the same D3D11 device. Thus no fence is needed.
It will also be useful for dcomp textures. Dcomp doesn't use the same
D3D11 device as Dawn. However it's not required to signal any fence
before returning the texture to dcomp. Dcomp still requires dawn to wait
on its own fence anw.

Bug: chromium:335003893
Change-Id: Ibf28cc5d84456f623b20f087cc23aa824e2131bd
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/235135
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Auto-Submit: Quyen Le <lehoangquyen@chromium.org>
Commit-Queue: Quyen Le <lehoangquyen@chromium.org>
diff --git a/include/dawn/native/D3D11Backend.h b/include/dawn/native/D3D11Backend.h
index e8fedd4..69c2a97 100644
--- a/include/dawn/native/D3D11Backend.h
+++ b/include/dawn/native/D3D11Backend.h
@@ -57,6 +57,13 @@
     // This ID3D11Texture2D object must be created from the same ID3D11Device used in the
     // WGPUDevice.
     Microsoft::WRL::ComPtr<ID3D11Texture2D> texture;
+
+    // If this flag is true, Dawn is required to signal a fence before EndAccess() and return it in
+    // SharedTextureMemoryEndAccessState's fences list.
+    // If it's false, no fence signaling is needed and EndAccess() might return empty fence list.
+    // Note: this flag is not relevant if the feature SharedFenceDXGISharedHandle is disabled/not
+    // supported.
+    bool requiresEndAcessFence = true;
 };
 
 }  // namespace dawn::native::d3d11
diff --git a/src/dawn/native/d3d11/SharedTextureMemoryD3D11.cpp b/src/dawn/native/d3d11/SharedTextureMemoryD3D11.cpp
index 4646963..0fc0d84 100644
--- a/src/dawn/native/d3d11/SharedTextureMemoryD3D11.cpp
+++ b/src/dawn/native/d3d11/SharedTextureMemoryD3D11.cpp
@@ -134,8 +134,8 @@
     DAWN_TRY_ASSIGN(properties, PropertiesFromD3D11Texture(device, d3d11Texture,
                                                            /*isSharedWithHandle=*/true));
 
-    auto result =
-        AcquireRef(new SharedTextureMemory(device, label, properties, std::move(d3d11Resource)));
+    auto result = AcquireRef(new SharedTextureMemory(
+        device, label, properties, std::move(d3d11Resource), /*requiresFenceSignal=*/true));
     result->Initialize();
     return result;
 }
@@ -161,8 +161,9 @@
     DAWN_TRY_ASSIGN(properties, PropertiesFromD3D11Texture(device, descriptor->texture,
                                                            /*isSharedWithHandle=*/false));
 
-    auto result =
-        AcquireRef(new SharedTextureMemory(device, label, properties, std::move(d3d11Resource)));
+    auto result = AcquireRef(
+        new SharedTextureMemory(device, label, properties, std::move(d3d11Resource),
+                                /*requiresFenceSignal=*/descriptor->requiresEndAcessFence));
     result->Initialize();
     return result;
 }
@@ -170,8 +171,11 @@
 SharedTextureMemory::SharedTextureMemory(Device* device,
                                          StringView label,
                                          SharedTextureMemoryProperties properties,
-                                         ComPtr<ID3D11Resource> resource)
-    : d3d::SharedTextureMemory(device, label, properties), mResource(std::move(resource)) {
+                                         ComPtr<ID3D11Resource> resource,
+                                         bool requiresFenceSignal)
+    : d3d::SharedTextureMemory(device, label, properties),
+      mResource(std::move(resource)),
+      mRequiresFenceSignal(requiresFenceSignal) {
     ComPtr<IDXGIKeyedMutex> dxgiKeyedMutex;
     mResource.As(&dxgiKeyedMutex);
     if (dxgiKeyedMutex) {
@@ -194,7 +198,7 @@
 
 ResultOrError<Ref<TextureBase>> SharedTextureMemory::CreateTextureImpl(
     const UnpackedPtr<TextureDescriptor>& descriptor) {
-    return Texture::CreateFromSharedTextureMemory(this, descriptor);
+    return Texture::CreateFromSharedTextureMemory(this, descriptor, mRequiresFenceSignal);
 }
 
 }  // namespace dawn::native::d3d11
diff --git a/src/dawn/native/d3d11/SharedTextureMemoryD3D11.h b/src/dawn/native/d3d11/SharedTextureMemoryD3D11.h
index d612ddb..49b24ff 100644
--- a/src/dawn/native/d3d11/SharedTextureMemoryD3D11.h
+++ b/src/dawn/native/d3d11/SharedTextureMemoryD3D11.h
@@ -61,7 +61,8 @@
     SharedTextureMemory(Device* device,
                         StringView label,
                         SharedTextureMemoryProperties properties,
-                        ComPtr<ID3D11Resource> resource);
+                        ComPtr<ID3D11Resource> resource,
+                        bool requiresFenceSignal);
 
     void DestroyImpl() override;
 
@@ -70,6 +71,9 @@
 
     ComPtr<ID3D11Resource> mResource;
     Ref<d3d::KeyedMutex> mKeyedMutex;
+
+    // Flag indicates whether we need to signal a fence after accessing this texture or not.
+    const bool mRequiresFenceSignal = true;
 };
 }  // namespace d3d11
 }  // namespace dawn::native
diff --git a/src/dawn/native/d3d11/TextureD3D11.cpp b/src/dawn/native/d3d11/TextureD3D11.cpp
index ea1f482..af9861d 100644
--- a/src/dawn/native/d3d11/TextureD3D11.cpp
+++ b/src/dawn/native/d3d11/TextureD3D11.cpp
@@ -203,9 +203,11 @@
 // static
 ResultOrError<Ref<Texture>> Texture::CreateFromSharedTextureMemory(
     SharedTextureMemory* memory,
-    const UnpackedPtr<TextureDescriptor>& descriptor) {
+    const UnpackedPtr<TextureDescriptor>& descriptor,
+    bool requiresFenceSignal) {
     Device* device = ToBackend(memory->GetDevice());
-    Ref<Texture> texture = AcquireRef(new Texture(device, descriptor, Kind::Normal));
+    Ref<Texture> texture =
+        AcquireRef(new Texture(device, descriptor, Kind::Normal, requiresFenceSignal));
     DAWN_TRY(
         texture->InitializeAsExternalTexture(memory->GetD3DResource(), memory->GetKeyedMutex()));
     texture->mSharedResourceMemoryContents = memory->GetContents();
@@ -331,8 +333,11 @@
     return {};
 }
 
-Texture::Texture(Device* device, const UnpackedPtr<TextureDescriptor>& descriptor, Kind kind)
-    : Base(device, descriptor), mKind(kind) {}
+Texture::Texture(Device* device,
+                 const UnpackedPtr<TextureDescriptor>& descriptor,
+                 Kind kind,
+                 bool requiresFenceSignal)
+    : Base(device, descriptor), mKind(kind), mRequiresFenceSignal(requiresFenceSignal) {}
 
 Texture::~Texture() = default;
 
@@ -470,7 +475,7 @@
                 CheckHRESULT(commandContext->Wait(d3dFence->GetD3DFence(), fence.signaledValue),
                              "ID3D11DeviceContext4::Wait"));
         }
-        if (!device->IsToggleEnabled(Toggle::D3D11DisableFence)) {
+        if (mRequiresFenceSignal && !device->IsToggleEnabled(Toggle::D3D11DisableFence)) {
             commandContext->SetNeedsFence();
         }
     }
diff --git a/src/dawn/native/d3d11/TextureD3D11.h b/src/dawn/native/d3d11/TextureD3D11.h
index 770c676..36374da 100644
--- a/src/dawn/native/d3d11/TextureD3D11.h
+++ b/src/dawn/native/d3d11/TextureD3D11.h
@@ -64,7 +64,8 @@
                                               ComPtr<ID3D11Resource> d3d11Texture);
     static ResultOrError<Ref<Texture>> CreateFromSharedTextureMemory(
         SharedTextureMemory* memory,
-        const UnpackedPtr<TextureDescriptor>& descriptor);
+        const UnpackedPtr<TextureDescriptor>& descriptor,
+        bool requiresFenceSignal);
     ID3D11Resource* GetD3D11Resource() const;
 
     struct RTVKey {
@@ -150,7 +151,10 @@
     static ResultOrError<Ref<Texture>>
     CreateInternal(Device* device, const UnpackedPtr<TextureDescriptor>& descriptor, Kind kind);
 
-    Texture(Device* device, const UnpackedPtr<TextureDescriptor>& descriptor, Kind kind);
+    Texture(Device* device,
+            const UnpackedPtr<TextureDescriptor>& descriptor,
+            Kind kind,
+            bool requiresFenceSignal = false);
     ~Texture() override;
 
     template <typename T>
@@ -213,6 +217,7 @@
     const Kind mKind = Kind::Normal;
     ComPtr<ID3D11Resource> mD3d11Resource;
     Ref<d3d::KeyedMutex> mKeyedMutex;
+    const bool mRequiresFenceSignal = false;
 
     // The internal 'R8Uint' texture for sampling stencil from depth-stencil textures.
     Ref<Texture> mTextureForStencilSampling;
diff --git a/src/dawn/tests/white_box/SharedTextureMemoryTests_win.cpp b/src/dawn/tests/white_box/SharedTextureMemoryTests_win.cpp
index 369e377..e1ac4b8 100644
--- a/src/dawn/tests/white_box/SharedTextureMemoryTests_win.cpp
+++ b/src/dawn/tests/white_box/SharedTextureMemoryTests_win.cpp
@@ -32,6 +32,7 @@
 #include <webgpu/webgpu_cpp.h>
 #include <wrl/client.h>
 
+#include <sstream>
 #include <string>
 #include <utility>
 #include <vector>
@@ -55,20 +56,36 @@
   public:
     template <Mode kMode>
     static Backend* GetInstance() {
-        static Backend b(kMode, false);
+        static Backend b(kMode, /*useKeyedMutex=*/false, /*requiresEndAccessFence=*/true);
         return &b;
     }
 
     template <Mode kMode>
     static Backend* GetKeyedMutexInstance() {
-        static Backend b(kMode, true);
+        static Backend b(kMode, /*useKeyedMutex=*/true, /*requiresEndAccessFence=*/true);
+        return &b;
+    }
+
+    static Backend* GetInstanceWithoutEndAccessFence() {
+        static Backend b(Mode::D3D11Texture2D, /*useKeyedMutex=*/false,
+                         /*requiresEndAccessFence=*/false);
         return &b;
     }
 
     std::string Name() const override {
         switch (mMode) {
             case Mode::D3D11Texture2D: {
-                return mUseKeyedMutex ? "D3D11Texture2D KeyedMutex" : "D3D11Texture2D";
+                std::ostringstream ss;
+                ss << "D3D11Texture2D";
+                if (mUseKeyedMutex) {
+                    ss << " KeyedMutex";
+                }
+
+                if (!mRequiresEndAccessFence) {
+                    ss << " NoEndAccessFence";
+                }
+
+                return ss.str();
             }
             case Mode::DXGISharedHandle: {
                 return mUseKeyedMutex ? "DXGISharedHandle KeyedMutex" : "DXGISharedHandle";
@@ -180,6 +197,7 @@
             case Mode::D3D11Texture2D: {
                 native::d3d11::SharedTextureMemoryD3D11Texture2DDescriptor texture2DDesc;
                 texture2DDesc.texture = std::move(d3d11Texture);
+                texture2DDesc.requiresEndAcessFence = mRequiresEndAccessFence;
 
                 wgpu::SharedTextureMemoryDescriptor desc;
                 desc.nextInChain = &texture2DDesc;
@@ -281,6 +299,7 @@
                     case Mode::D3D11Texture2D: {
                         native::d3d11::SharedTextureMemoryD3D11Texture2DDescriptor texture2DDesc;
                         texture2DDesc.texture = d3d11Texture;
+                        texture2DDesc.requiresEndAcessFence = mRequiresEndAccessFence;
 
                         wgpu::SharedTextureMemoryDescriptor desc;
                         desc.nextInChain = &texture2DDesc;
@@ -338,10 +357,14 @@
     }
 
   private:
-    Backend(Mode mode, bool useKeyedMutex) : mMode(mode), mUseKeyedMutex(useKeyedMutex) {}
+    Backend(Mode mode, bool useKeyedMutex, bool requiresEndAccessFence)
+        : mMode(mode),
+          mUseKeyedMutex(useKeyedMutex),
+          mRequiresEndAccessFence(requiresEndAccessFence) {}
 
     const Mode mMode;
     const bool mUseKeyedMutex;
+    const bool mRequiresEndAccessFence;
 };
 
 // Test that it is an error to import a shared fence without enabling the feature.
@@ -568,14 +591,16 @@
                                  SharedTextureMemoryNoFeatureTests,
                                  {D3D11Backend(), D3D11Backend({"d3d11_disable_fence"})},
                                  {Backend::GetInstance<Mode::D3D11Texture2D>(),
-                                  Backend::GetKeyedMutexInstance<Mode::D3D11Texture2D>()},
+                                  Backend::GetKeyedMutexInstance<Mode::D3D11Texture2D>(),
+                                  Backend::GetInstanceWithoutEndAccessFence()},
                                  {1, 2});
 
 DAWN_INSTANTIATE_PREFIXED_TEST_P(D3D11,
                                  SharedTextureMemoryTests,
                                  {D3D11Backend(), D3D11Backend({"d3d11_disable_fence"})},
                                  {Backend::GetInstance<Mode::D3D11Texture2D>(),
-                                  Backend::GetKeyedMutexInstance<Mode::D3D11Texture2D>()},
+                                  Backend::GetKeyedMutexInstance<Mode::D3D11Texture2D>(),
+                                  Backend::GetInstanceWithoutEndAccessFence()},
                                  {1, 2});
 
 DAWN_INSTANTIATE_PREFIXED_TEST_P(D3D11,