D3D11: Allow dynamically skipping fence signals in BeginAccess

Previously, fence signaling for a Shared Texture Manager (STM) was
configured only at creation. This change adds a new option to
BeginAccessDescriptor to control fence signaling dynamically at the time
of access.

This enables use cases where a shared image can initially have fence
signaling disabled and then enforce it after the first WebGPU access.

The older creation-time option will be removed once clients adopt this
new descriptor.

Bug: chromium:429093435
Change-Id: If6bab8749d96bd667a88a3e661b1ffa066481102
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/250434
Reviewed-by: Loko Kung <lokokung@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Quyen Le <lehoangquyen@chromium.org>
diff --git a/include/dawn/native/D3D11Backend.h b/include/dawn/native/D3D11Backend.h
index 0fd8ba0..415b97e 100644
--- a/include/dawn/native/D3D11Backend.h
+++ b/include/dawn/native/D3D11Backend.h
@@ -32,6 +32,7 @@
 #include <wrl/client.h>
 
 #include <memory>
+#include <optional>
 
 #include "dawn/native/D3DBackend.h"
 
@@ -61,9 +62,14 @@
     // 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
+    // Notes:
+    // - This flag is not relevant if the feature SharedFenceDXGISharedHandle is disabled/not
     // supported.
-    bool requiresEndAccessFence = true;
+    // - This flag if present will override the requiresEndAccessFence flag in
+    // SharedTextureMemoryD3D11BeginState
+    // TODO(chromium:335003893): This flag is deprecated. Remove it once clients are updated to use
+    // SharedTextureMemoryD3D11BeginState's requiresEndAccessFence.
+    std::optional<bool> requiresEndAccessFence;
 };
 
 }  // namespace dawn::native::d3d11
diff --git a/src/dawn/dawn.json b/src/dawn/dawn.json
index 377e1d6..c082644 100644
--- a/src/dawn/dawn.json
+++ b/src/dawn/dawn.json
@@ -2066,6 +2066,15 @@
             {"name": "is swapchain", "type": "bool", "default": "false"}
         ]
     },
+    "shared texture memory D3D11 begin state": {
+        "category": "structure",
+        "chained": "in",
+        "chain roots": ["shared texture memory begin access descriptor"],
+        "tags": ["dawn", "native"],
+        "members": [
+            {"name": "requires end access fence", "type": "bool", "default": "true"}
+        ]
+    },
     "shared fence": {
         "category": "object",
         "tags": ["dawn", "native"],
@@ -3880,7 +3889,8 @@
             {"value": 68, "name": "render pass descriptor resolve rect", "tags": ["dawn"]},
             {"value": 69, "name": "request adapter WebGPU backend options", "tags": ["dawn", "native"]},
             {"value": 70, "name": "dawn fake device initialize error for testing", "tags": ["dawn"]},
-            {"value": 71, "name": "texture component swizzle descriptor", "tags": ["dawn"]}
+            {"value": 71, "name": "texture component swizzle descriptor", "tags": ["dawn"]},
+            {"value": 72, "name": "shared texture memory D3D11 begin state", "tags": ["dawn", "native"]}
         ]
     },
     "texture": {
diff --git a/src/dawn/native/SharedResourceMemory.cpp b/src/dawn/native/SharedResourceMemory.cpp
index cf8f69d..679bc32 100644
--- a/src/dawn/native/SharedResourceMemory.cpp
+++ b/src/dawn/native/SharedResourceMemory.cpp
@@ -66,6 +66,10 @@
     return mReadAccessCount;
 }
 
+bool SharedResourceMemoryContents::HasAccess() const {
+    return mSharedResourceAccessState != SharedResourceAccessState::NotAccessed;
+}
+
 void SharedResourceMemory::Initialize() {
     DAWN_ASSERT(!IsError());
     mContents = CreateContents();
diff --git a/src/dawn/native/SharedResourceMemory.h b/src/dawn/native/SharedResourceMemory.h
index c552299..0b0a00e 100644
--- a/src/dawn/native/SharedResourceMemory.h
+++ b/src/dawn/native/SharedResourceMemory.h
@@ -163,6 +163,7 @@
     bool HasWriteAccess() const;
     bool HasExclusiveReadAccess() const;
     int GetReadAccessCount() const;
+    bool HasAccess() const;
 
   private:
     friend class SharedResourceMemory;
diff --git a/src/dawn/native/d3d/SharedTextureMemoryD3D.cpp b/src/dawn/native/d3d/SharedTextureMemoryD3D.cpp
index 59ad1e5..2f3dbac 100644
--- a/src/dawn/native/d3d/SharedTextureMemoryD3D.cpp
+++ b/src/dawn/native/d3d/SharedTextureMemoryD3D.cpp
@@ -46,7 +46,8 @@
 MaybeError SharedTextureMemory::BeginAccessImpl(
     TextureBase* texture,
     const UnpackedPtr<BeginAccessDescriptor>& descriptor) {
-    DAWN_TRY(descriptor.ValidateSubset<SharedTextureMemoryD3DSwapchainBeginState>());
+    DAWN_TRY((descriptor.ValidateSubset<SharedTextureMemoryD3DSwapchainBeginState,
+                                        SharedTextureMemoryD3D11BeginState>()));
     for (size_t i = 0; i < descriptor->fenceCount; ++i) {
         SharedFenceBase* fence = descriptor->fences[i];
 
diff --git a/src/dawn/native/d3d11/SharedTextureMemoryD3D11.cpp b/src/dawn/native/d3d11/SharedTextureMemoryD3D11.cpp
index 6f6b04a..4c7f775 100644
--- a/src/dawn/native/d3d11/SharedTextureMemoryD3D11.cpp
+++ b/src/dawn/native/d3d11/SharedTextureMemoryD3D11.cpp
@@ -134,8 +134,9 @@
     DAWN_TRY_ASSIGN(properties, PropertiesFromD3D11Texture(device, d3d11Texture,
                                                            /*isSharedWithHandle=*/true));
 
-    auto result = AcquireRef(new SharedTextureMemory(
-        device, label, properties, std::move(d3d11Resource), /*requiresFenceSignal=*/true));
+    auto result =
+        AcquireRef(new SharedTextureMemory(device, label, properties, std::move(d3d11Resource),
+                                           /*requiresFenceSignalOverride=*/std::nullopt));
     result->Initialize();
     return result;
 }
@@ -161,9 +162,9 @@
     DAWN_TRY_ASSIGN(properties, PropertiesFromD3D11Texture(device, descriptor->texture,
                                                            /*isSharedWithHandle=*/false));
 
-    auto result = AcquireRef(
-        new SharedTextureMemory(device, label, properties, std::move(d3d11Resource),
-                                /*requiresFenceSignal=*/descriptor->requiresEndAccessFence));
+    auto result = AcquireRef(new SharedTextureMemory(
+        device, label, properties, std::move(d3d11Resource),
+        /*requiresFenceSignalOverride=*/descriptor->requiresEndAccessFence));
     result->Initialize();
     return result;
 }
@@ -172,10 +173,10 @@
                                          StringView label,
                                          SharedTextureMemoryProperties properties,
                                          ComPtr<ID3D11Resource> resource,
-                                         bool requiresFenceSignal)
+                                         std::optional<bool> requiresFenceSignalOverride)
     : d3d::SharedTextureMemory(device, label, properties),
       mResource(std::move(resource)),
-      mRequiresFenceSignal(requiresFenceSignal) {
+      mRequiresFenceSignalOverride(std::move(requiresFenceSignalOverride)) {
     ComPtr<IDXGIKeyedMutex> dxgiKeyedMutex;
     mResource.As(&dxgiKeyedMutex);
     if (dxgiKeyedMutex) {
@@ -198,7 +199,48 @@
 
 ResultOrError<Ref<TextureBase>> SharedTextureMemory::CreateTextureImpl(
     const UnpackedPtr<TextureDescriptor>& descriptor) {
-    return Texture::CreateFromSharedTextureMemory(this, descriptor, mRequiresFenceSignal);
+    return Texture::CreateFromSharedTextureMemory(this, descriptor);
+}
+
+Ref<SharedResourceMemoryContents> SharedTextureMemory::CreateContents() {
+    return AcquireRef(new SharedTextureMemoryContentsD3D11(GetWeakRef(this)));
+}
+
+MaybeError SharedTextureMemory::BeginAccessImpl(
+    TextureBase* texture,
+    const UnpackedPtr<SharedTextureMemoryBeginAccessDescriptor>& descriptor) {
+    DAWN_TRY(d3d::SharedTextureMemory::BeginAccessImpl(texture, descriptor));
+
+    auto* contents = static_cast<SharedTextureMemoryContentsD3D11*>(GetContents());
+
+    if (mRequiresFenceSignalOverride) {
+        contents->mRequiresFenceSignal = *mRequiresFenceSignalOverride;
+    } else if (auto* d3d11beginState = descriptor.Get<SharedTextureMemoryD3D11BeginState>()) {
+        contents->mRequiresFenceSignal |= d3d11beginState->requiresEndAccessFence;
+    } else {
+        // If there is no SharedTextureMemoryD3D11BeginState, default to true
+        contents->mRequiresFenceSignal = true;
+    }
+
+    return {};
+}
+
+ResultOrError<FenceAndSignalValue> SharedTextureMemory::EndAccessImpl(
+    TextureBase* texture,
+    ExecutionSerial lastUsageSerial,
+    UnpackedPtr<SharedTextureMemoryEndAccessState>& descriptor) {
+    FenceAndSignalValue fenceAndSignalValue;
+
+    DAWN_TRY_ASSIGN(fenceAndSignalValue,
+                    d3d::SharedTextureMemory::EndAccessImpl(texture, lastUsageSerial, descriptor));
+
+    auto* contents = static_cast<SharedTextureMemoryContentsD3D11*>(GetContents());
+    if (!contents->HasAccess()) {
+        // Reset fence requirement flag.
+        contents->mRequiresFenceSignal = false;
+    }
+
+    return fenceAndSignalValue;
 }
 
 }  // namespace dawn::native::d3d11
diff --git a/src/dawn/native/d3d11/SharedTextureMemoryD3D11.h b/src/dawn/native/d3d11/SharedTextureMemoryD3D11.h
index 49b24ff..da5a37e 100644
--- a/src/dawn/native/d3d11/SharedTextureMemoryD3D11.h
+++ b/src/dawn/native/d3d11/SharedTextureMemoryD3D11.h
@@ -28,6 +28,8 @@
 #ifndef SRC_DAWN_NATIVE_D3D11_SHARED_TEXTURE_MEMORY_D3D11_H_
 #define SRC_DAWN_NATIVE_D3D11_SHARED_TEXTURE_MEMORY_D3D11_H_
 
+#include <optional>
+
 #include "dawn/native/Error.h"
 #include "dawn/native/d3d/SharedTextureMemoryD3D.h"
 #include "dawn/native/d3d/d3d_platform.h"
@@ -41,6 +43,20 @@
 class Device;
 struct SharedTextureMemoryD3D11Texture2DDescriptor;
 
+class SharedTextureMemoryContentsD3D11 final : public SharedTextureMemoryContents {
+  public:
+    using SharedTextureMemoryContents::SharedTextureMemoryContents;
+
+    bool RequiresFenceSignal() const { return mRequiresFenceSignal; }
+
+  private:
+    friend class SharedTextureMemory;
+
+    // Flag indicates whether we need to signal a fence after accessing this texture or not.
+    // This flag will be updated in BeginAccess() & reset in EndAccess().
+    bool mRequiresFenceSignal = false;
+};
+
 class SharedTextureMemory final : public d3d::SharedTextureMemory {
   public:
     static ResultOrError<Ref<SharedTextureMemory>> Create(
@@ -62,18 +78,29 @@
                         StringView label,
                         SharedTextureMemoryProperties properties,
                         ComPtr<ID3D11Resource> resource,
-                        bool requiresFenceSignal);
+                        std::optional<bool> requiresFenceSignalOverride = std::nullopt);
 
     void DestroyImpl() override;
 
     ResultOrError<Ref<TextureBase>> CreateTextureImpl(
         const UnpackedPtr<TextureDescriptor>& descriptor) override;
 
+    Ref<SharedResourceMemoryContents> CreateContents() override;
+
+    MaybeError BeginAccessImpl(TextureBase* texture,
+                               const UnpackedPtr<BeginAccessDescriptor>& descriptor) override;
+    ResultOrError<FenceAndSignalValue> EndAccessImpl(
+        TextureBase* texture,
+        ExecutionSerial lastUsageSerial,
+        UnpackedPtr<EndAccessState>& descriptor) override;
+
     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;
+    // TODO(chromium:335003893): This flag is deprecated. Remove it once clients are updated to use
+    // SharedTextureMemoryD3D11BeginState's requiresEndAccessFence.
+    const std::optional<bool> mRequiresFenceSignalOverride;
 };
 }  // namespace d3d11
 }  // namespace dawn::native
diff --git a/src/dawn/native/d3d11/TextureD3D11.cpp b/src/dawn/native/d3d11/TextureD3D11.cpp
index bcc01c3..6885a96 100644
--- a/src/dawn/native/d3d11/TextureD3D11.cpp
+++ b/src/dawn/native/d3d11/TextureD3D11.cpp
@@ -175,11 +175,9 @@
 // static
 ResultOrError<Ref<Texture>> Texture::CreateFromSharedTextureMemory(
     SharedTextureMemory* memory,
-    const UnpackedPtr<TextureDescriptor>& descriptor,
-    bool requiresFenceSignal) {
+    const UnpackedPtr<TextureDescriptor>& descriptor) {
     Device* device = ToBackend(memory->GetDevice());
-    Ref<Texture> texture =
-        AcquireRef(new Texture(device, descriptor, Kind::Normal, requiresFenceSignal));
+    Ref<Texture> texture = AcquireRef(new Texture(device, descriptor, Kind::Normal));
     DAWN_TRY(
         texture->InitializeAsExternalTexture(memory->GetD3DResource(), memory->GetKeyedMutex()));
     texture->mSharedResourceMemoryContents = memory->GetContents();
@@ -305,11 +303,8 @@
     return {};
 }
 
-Texture::Texture(Device* device,
-                 const UnpackedPtr<TextureDescriptor>& descriptor,
-                 Kind kind,
-                 bool requiresFenceSignal)
-    : Base(device, descriptor), mKind(kind), mRequiresFenceSignal(requiresFenceSignal) {}
+Texture::Texture(Device* device, const UnpackedPtr<TextureDescriptor>& descriptor, Kind kind)
+    : Base(device, descriptor), mKind(kind) {}
 
 Texture::~Texture() = default;
 
@@ -424,7 +419,8 @@
 
 MaybeError Texture::SynchronizeTextureBeforeUse(
     const ScopedCommandRecordingContext* commandContext) {
-    if (auto* contents = GetSharedResourceMemoryContents()) {
+    if (auto* contents =
+            static_cast<SharedTextureMemoryContentsD3D11*>(GetSharedResourceMemoryContents())) {
         const auto* device = ToBackend(GetDevice());
         const auto& queueFence = ToBackend(device->GetQueue())->GetSharedFence();
 
@@ -442,7 +438,9 @@
                 CheckHRESULT(commandContext->Wait(d3dFence->GetD3DFence(), fence.signaledValue),
                              "ID3D11DeviceContext4::Wait"));
         }
-        if (mRequiresFenceSignal && !device->IsToggleEnabled(Toggle::D3D11DisableFence)) {
+
+        const bool requiresFenceSignal = contents->RequiresFenceSignal();
+        if (requiresFenceSignal && !device->IsToggleEnabled(Toggle::D3D11DisableFence)) {
             commandContext->SetNeedsFence();
         }
     }
diff --git a/src/dawn/native/d3d11/TextureD3D11.h b/src/dawn/native/d3d11/TextureD3D11.h
index e182bff..e3a5928 100644
--- a/src/dawn/native/d3d11/TextureD3D11.h
+++ b/src/dawn/native/d3d11/TextureD3D11.h
@@ -64,8 +64,7 @@
                                               ComPtr<ID3D11Resource> d3d11Texture);
     static ResultOrError<Ref<Texture>> CreateFromSharedTextureMemory(
         SharedTextureMemory* memory,
-        const UnpackedPtr<TextureDescriptor>& descriptor,
-        bool requiresFenceSignal);
+        const UnpackedPtr<TextureDescriptor>& descriptor);
     ID3D11Resource* GetD3D11Resource() const;
 
     ResultOrError<ComPtr<ID3D11RenderTargetView1>> CreateD3D11RenderTargetView(
@@ -132,10 +131,7 @@
     static ResultOrError<Ref<Texture>>
     CreateInternal(Device* device, const UnpackedPtr<TextureDescriptor>& descriptor, Kind kind);
 
-    Texture(Device* device,
-            const UnpackedPtr<TextureDescriptor>& descriptor,
-            Kind kind,
-            bool requiresFenceSignal = false);
+    Texture(Device* device, const UnpackedPtr<TextureDescriptor>& descriptor, Kind kind);
     ~Texture() override;
 
     template <typename T>
@@ -198,7 +194,6 @@
     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 d232e0d..07798bf 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 <memory>
 #include <sstream>
 #include <string>
 #include <utility>
@@ -52,6 +53,10 @@
     D3D11Texture2D,
 };
 
+struct BeginState : public SharedTextureMemoryTestBackend::BackendBeginState {
+    wgpu::SharedTextureMemoryD3D11BeginState beginState{};
+};
+
 class Backend : public SharedTextureMemoryTestBackend {
   public:
     template <Mode kMode>
@@ -66,34 +71,37 @@
         return &b;
     }
 
+    template <Mode kMode>
     static Backend* GetInstanceWithoutEndAccessFence() {
-        static Backend b(Mode::D3D11Texture2D, /*useKeyedMutex=*/false,
+        static Backend b(kMode, /*useKeyedMutex=*/false,
                          /*requiresEndAccessFence=*/false);
         return &b;
     }
 
     std::string Name() const override {
+        std::ostringstream ss;
         switch (mMode) {
             case Mode::D3D11Texture2D: {
-                std::ostringstream ss;
                 ss << "D3D11Texture2D";
-                if (mUseKeyedMutex) {
-                    ss << " KeyedMutex";
-                }
-
-                if (!mRequiresEndAccessFence) {
-                    ss << " NoEndAccessFence";
-                }
-
-                return ss.str();
-            }
+            } break;
             case Mode::DXGISharedHandle: {
-                return mUseKeyedMutex ? "DXGISharedHandle KeyedMutex" : "DXGISharedHandle";
-            }
+                ss << "DXGISharedHandle";
+            } break;
         }
+        if (mUseKeyedMutex) {
+            ss << " KeyedMutex";
+        }
+
+        if (!mRequiresEndAccessFence) {
+            ss << " NoEndAccessFence";
+        }
+
+        return ss.str();
     }
 
-    bool UseSameDevice() const override { return mMode == Mode::D3D11Texture2D; }
+    bool UseSameDevice() const override {
+        return mMode == Mode::D3D11Texture2D || !mRequiresEndAccessFence;
+    }
     bool SupportsConcurrentRead() const override { return true; }
 
     void SetUp(const wgpu::Device& device) override {
@@ -197,7 +205,6 @@
             case Mode::D3D11Texture2D: {
                 native::d3d11::SharedTextureMemoryD3D11Texture2DDescriptor texture2DDesc;
                 texture2DDesc.texture = std::move(d3d11Texture);
-                texture2DDesc.requiresEndAccessFence = mRequiresEndAccessFence;
 
                 wgpu::SharedTextureMemoryDescriptor desc;
                 desc.nextInChain = &texture2DDesc;
@@ -356,6 +363,20 @@
         return memories;
     }
 
+    std::unique_ptr<BackendBeginState> ChainInitialBeginState(
+        wgpu::SharedTextureMemoryBeginAccessDescriptor* beginDesc) override {
+        auto state = std::make_unique<BeginState>();
+        state->beginState.requiresEndAccessFence = mRequiresEndAccessFence;
+        beginDesc->nextInChain = &state->beginState;
+        return state;
+    }
+
+    std::unique_ptr<BackendBeginState> ChainBeginState(
+        wgpu::SharedTextureMemoryBeginAccessDescriptor* beginDesc,
+        const wgpu::SharedTextureMemoryEndAccessState& endState) override {
+        return ChainInitialBeginState(beginDesc);
+    }
+
   private:
     Backend(Mode mode, bool useKeyedMutex, bool requiresEndAccessFence)
         : mMode(mode),
@@ -579,30 +600,34 @@
                                   Backend::GetKeyedMutexInstance<Mode::DXGISharedHandle>()},
                                  {1});
 
-DAWN_INSTANTIATE_PREFIXED_TEST_P(D3D,
-                                 SharedTextureMemoryTests,
-                                 {D3D11Backend(), D3D11Backend({"d3d11_delay_flush_to_gpu"}),
-                                  D3D11Backend({"d3d11_disable_fence"}), D3D12Backend()},
-                                 {Backend::GetInstance<Mode::DXGISharedHandle>(),
-                                  Backend::GetKeyedMutexInstance<Mode::DXGISharedHandle>()},
-                                 {1});
+DAWN_INSTANTIATE_PREFIXED_TEST_P(
+    D3D,
+    SharedTextureMemoryTests,
+    {D3D11Backend(), D3D11Backend({"d3d11_delay_flush_to_gpu"}),
+     D3D11Backend({"d3d11_disable_fence"}), D3D12Backend()},
+    {Backend::GetInstance<Mode::DXGISharedHandle>(),
+     Backend::GetKeyedMutexInstance<Mode::DXGISharedHandle>(),
+     Backend::GetInstanceWithoutEndAccessFence<Mode::DXGISharedHandle>()},
+    {1});
 
-DAWN_INSTANTIATE_PREFIXED_TEST_P(D3D11,
-                                 SharedTextureMemoryNoFeatureTests,
-                                 {D3D11Backend(), D3D11Backend({"d3d11_disable_fence"})},
-                                 {Backend::GetInstance<Mode::D3D11Texture2D>(),
-                                  Backend::GetKeyedMutexInstance<Mode::D3D11Texture2D>(),
-                                  Backend::GetInstanceWithoutEndAccessFence()},
-                                 {1, 2});
+DAWN_INSTANTIATE_PREFIXED_TEST_P(
+    D3D11,
+    SharedTextureMemoryNoFeatureTests,
+    {D3D11Backend(), D3D11Backend({"d3d11_disable_fence"})},
+    {Backend::GetInstance<Mode::D3D11Texture2D>(),
+     Backend::GetKeyedMutexInstance<Mode::D3D11Texture2D>(),
+     Backend::GetInstanceWithoutEndAccessFence<Mode::D3D11Texture2D>()},
+    {1, 2});
 
-DAWN_INSTANTIATE_PREFIXED_TEST_P(D3D11,
-                                 SharedTextureMemoryTests,
-                                 {D3D11Backend(), D3D11Backend({"d3d11_delay_flush_to_gpu"}),
-                                  D3D11Backend({"d3d11_disable_fence"})},
-                                 {Backend::GetInstance<Mode::D3D11Texture2D>(),
-                                  Backend::GetKeyedMutexInstance<Mode::D3D11Texture2D>(),
-                                  Backend::GetInstanceWithoutEndAccessFence()},
-                                 {1, 2});
+DAWN_INSTANTIATE_PREFIXED_TEST_P(
+    D3D11,
+    SharedTextureMemoryTests,
+    {D3D11Backend(), D3D11Backend({"d3d11_delay_flush_to_gpu"}),
+     D3D11Backend({"d3d11_disable_fence"})},
+    {Backend::GetInstance<Mode::D3D11Texture2D>(),
+     Backend::GetKeyedMutexInstance<Mode::D3D11Texture2D>(),
+     Backend::GetInstanceWithoutEndAccessFence<Mode::D3D11Texture2D>()},
+    {1, 2});
 
 DAWN_INSTANTIATE_PREFIXED_TEST_P(D3D11,
                                  SharedTextureMemoryWithFenceDisabledTests,