D3D11: Add a toggle to delay D3D11's Flush.
D3D11's Flush/Signal calls have fixed costs. Calling them too frequently
could be expensive. Ideally we should only call them once per frame in
applications such as chrome. However, that is not always possible
because some times chrome's renderer process has to call
RasterInterface::Flush() that triggers Queue::Submit() which ultimately
leads to D3D11's Flush/Signal.
This CL adds a toggle to prevents Queue::Submit() from automatically
triggering D3D11's Flush. What this means is that Queue::Submmit() won't
send the commands to the GPU immediately. It will still do other things
such as converting Dawn's commands to D3D11 commands and queue them in
the driver's internal command buffer. In order to send the commands to
the GPU for good, clients will need to either:
- Call IDXGISwapChain::Present either via SwapChain class or
externally.
- Use WaitAny() to wait for a GPU work/buffer mapping to complete.
- Repeatedly call Device::Tick() or Queue::Submit().
Without Flush, we need other ways to track the work completions.
Previously SystemEvent would be used, but it would require a Flush.
This CL will utilize another primitive (ID3D11Query) to track the works.
It won't require a Flush.
Notes:
- This CL would make RasterInterface::Flush()'s behaviors with Dawn
similar to when it uses ANGLE. With ANGLE, RasterInterface::Flush()
doesn't send the commands to the GPU. It only issues GL draw calls but
doesn't trigger glFlush().
- The new toggle won't eliminate the Signal() calls in Queue::Submit()
entirely. However, Signal() is only triggered when applications use
DXGISharedHandle textures, so the frequency of this happening is not
high.
Bug: chromium:377716220
Bug: 416736350
Change-Id: I5cb1c9c73d24fa63c6fe7dfcb7308cb0c3343049
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/235134
Commit-Queue: Quyen Le <lehoangquyen@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Auto-Submit: Quyen Le <lehoangquyen@chromium.org>
Reviewed-by: Loko Kung <lokokung@google.com>
diff --git a/src/dawn/native/Toggles.cpp b/src/dawn/native/Toggles.cpp
index 0815ee8..7d7324f 100644
--- a/src/dawn/native/Toggles.cpp
+++ b/src/dawn/native/Toggles.cpp
@@ -680,6 +680,13 @@
{"d3d11_disable_fence",
"Disable d3d11 fence. Fences are not always available on every D3D11 device.",
"https://crbug.com/chromium/390441217", ToggleStage::Device}},
+ {Toggle::D3D11DelayFlushToGPU,
+ {"d3d11_delay_flush_to_gpu",
+ "When this toggle is enabled, Queue::Submit() might not flush the commands to GPU "
+ "immediately. A flush will happen when IDXGISwapChain::Present() is called or applications "
+ "use Instance.WaitAny() to wait for a GPU operation to finish. This toggle is intended to "
+ "reduce the fixed overhead associated with each flushing.",
+ "https://crbug.com/chromium/377716220", ToggleStage::Device}},
{Toggle::IgnoreImportedAHardwareBufferVulkanImageSize,
{"ignore_imported_ahardwarebuffer_vulkan_image_size",
"Don't validate the required VkImage size against the size of the AHardwareBuffer on import. "
diff --git a/src/dawn/native/Toggles.h b/src/dawn/native/Toggles.h
index ffd3695..92ac359 100644
--- a/src/dawn/native/Toggles.h
+++ b/src/dawn/native/Toggles.h
@@ -164,6 +164,7 @@
D3D11UseUnmonitoredFence,
D3D11DisableFence,
+ D3D11DelayFlushToGPU,
IgnoreImportedAHardwareBufferVulkanImageSize,
EnumCount,
diff --git a/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp b/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp
index 9524c64..aa7125e 100644
--- a/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp
+++ b/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp
@@ -115,6 +115,21 @@
return Get()->mD3D11DeviceContext4->Wait(pFence, Value);
}
+HRESULT ScopedCommandRecordingContext::GetData(ID3D11Query* pQuery,
+ void* pResult,
+ UINT size,
+ UINT flags) const {
+ return Get()->mD3D11DeviceContext3->GetData(pQuery, pResult, size, flags);
+}
+
+void ScopedCommandRecordingContext::End(ID3D11Query* pQuery) const {
+ Get()->mD3D11DeviceContext3->End(pQuery);
+}
+
+void ScopedCommandRecordingContext::Flush() const {
+ return Get()->mD3D11DeviceContext3->Flush();
+}
+
void ScopedCommandRecordingContext::Flush1(D3D11_CONTEXT_TYPE ContextType, HANDLE hEvent) const {
return Get()->mD3D11DeviceContext3->Flush1(ContextType, hEvent);
}
diff --git a/src/dawn/native/d3d11/CommandRecordingContextD3D11.h b/src/dawn/native/d3d11/CommandRecordingContextD3D11.h
index 15988f3..3a8c5ff 100644
--- a/src/dawn/native/d3d11/CommandRecordingContextD3D11.h
+++ b/src/dawn/native/d3d11/CommandRecordingContextD3D11.h
@@ -163,6 +163,9 @@
void Unmap(ID3D11Resource* pResource, UINT Subresource) const;
HRESULT Signal(ID3D11Fence* pFence, UINT64 Value) const;
HRESULT Wait(ID3D11Fence* pFence, UINT64 Value) const;
+ HRESULT GetData(ID3D11Query* pQuery, void* pResult, UINT size, UINT flags) const;
+ void End(ID3D11Query* pQuery) const;
+ void Flush() const;
void Flush1(D3D11_CONTEXT_TYPE ContextType, HANDLE hEvent) const;
// Write the built-in variable value to the uniform buffer.
diff --git a/src/dawn/native/d3d11/QueueD3D11.cpp b/src/dawn/native/d3d11/QueueD3D11.cpp
index 677fc52..3a20654 100644
--- a/src/dawn/native/d3d11/QueueD3D11.cpp
+++ b/src/dawn/native/d3d11/QueueD3D11.cpp
@@ -28,8 +28,11 @@
#include "dawn/native/d3d11/QueueD3D11.h"
#include <algorithm>
+#include <chrono>
#include <deque>
+#include <iterator>
#include <limits>
+#include <thread>
#include <utility>
#include <vector>
@@ -48,8 +51,10 @@
#include "dawn/platform/tracing/TraceEvent.h"
namespace dawn::native::d3d11 {
+namespace {
-class MonitoredQueue final : public Queue {
+// Queue's subclass that uses monitored fences exclusively to signal/track work done.
+class MonitoredFenceQueue final : public Queue {
public:
using Queue::Queue;
MaybeError Initialize();
@@ -58,9 +63,10 @@
void SetEventOnCompletion(ExecutionSerial serial, HANDLE event) override;
private:
- ~MonitoredQueue() override = default;
+ ~MonitoredFenceQueue() override = default;
};
+// Queue's subclass that uses SystemEvent + Flush1 to track work done.
class SystemEventQueue final : public Queue {
public:
using Queue::Queue;
@@ -84,38 +90,102 @@
MutexProtected<std::vector<SerialEventReceiverPair>> mCompletedEvents;
};
+// Queue's subclass that doesn't flush the commands to GPU immediately in Submit().
+// This class uses ID3D11Query to track a serial's work completion. ID3D11Query::GetData() can be
+// used to check whether the serial has passed or not.
+// Note that if the commands were never sent to the GPU, ID3D11Query::GetData() might never return
+// true and the application might wait indefinitely for a serial to complete. Thus, a flush must be
+// triggered implicitly at some points. For the current implementation, a flush will be triggered
+// when one of the following conditions is met:
+// - Application calls IDXGISwapChain::Present() either via SwapChain class or externally.
+// - Application calls WaitAny() to wait for a GPU operation/buffer mapping to finish.
+// - ID3D11Query::GetData() has been called N times. This can be triggered indirectly via:
+// - Calling Device::Tick() or Queue::Submit() N times.
+// - Both the above methods indirectly trigger CheckAndUpdateCompletedSerials() which in turn
+// calls ID3D11Query::GetData() N times.
+class DelayFlushQueue final : public Queue {
+ public:
+ using Queue::Queue;
+ MaybeError Initialize();
+ MaybeError NextSerial() override;
+ ResultOrError<ExecutionSerial> CheckAndUpdateCompletedSerials() override;
+ ResultOrError<bool> WaitForQueueSerial(ExecutionSerial serial, Nanoseconds timeout) override;
+ void SetEventOnCompletion(ExecutionSerial serial, HANDLE event) override;
+
+ private:
+ ~DelayFlushQueue() override = default;
+
+ // Check for completed serials in the pending list.
+ MaybeError CheckPendingQueries(const ScopedCommandRecordingContext* commandContext);
+
+ void MarkPendingQueriesAsComplete(size_t numCompletedQueries);
+
+ struct EventQuery {
+ public:
+ EventQuery(ExecutionSerial serial, ComPtr<ID3D11Query> query)
+ : mSerial(serial), mQuery(std::move(query)) {}
+
+ ExecutionSerial Serial() const { return mSerial; }
+ ComPtr<ID3D11Query> AcquireQuery() { return std::move(mQuery); }
+ ID3D11Query* GetQuery() { return mQuery.Get(); }
+
+ // Number of GetData() calls on this query.
+ size_t checkCount = 0;
+
+ private:
+ ExecutionSerial mSerial;
+ ComPtr<ID3D11Query> mQuery;
+ };
+
+ ResultOrError<bool> IsQueryCompleted(const ScopedCommandRecordingContext* commandContext,
+ bool requireFlush,
+ EventQuery* eventQuery);
+
+ // Events associated with submitted commands. They are in old to recent order.
+ std::deque<EventQuery> mPendingQueries;
+ // List of completed queries to be recycled in CheckAndUpdateCompletedSerials().
+ std::vector<EventQuery> mCompletedQueries;
+ // List of recycled queries.
+ std::vector<ComPtr<ID3D11Query>> mFreeQueries;
+};
+
+} // namespace
+
ResultOrError<Ref<Queue>> Queue::Create(Device* device, const QueueDescriptor* descriptor) {
const auto& deviceInfo = ToBackend(device->GetPhysicalDevice())->GetDeviceInfo();
+ if (device->IsToggleEnabled(Toggle::D3D11DelayFlushToGPU)) {
+ auto queue = AcquireRef(new DelayFlushQueue(device, descriptor));
+ DAWN_TRY(queue->Initialize());
+ return queue;
+ }
+
if (device->IsToggleEnabled(Toggle::D3D11UseUnmonitoredFence) ||
device->IsToggleEnabled(Toggle::D3D11DisableFence)) {
- Ref<SystemEventQueue> systemEventQueue =
- AcquireRef(new SystemEventQueue(device, descriptor));
- DAWN_TRY(systemEventQueue->Initialize());
- return systemEventQueue;
- } else if (deviceInfo.supportsMonitoredFence) {
- Ref<MonitoredQueue> monitoredQueue = AcquireRef(new MonitoredQueue(device, descriptor));
- DAWN_TRY(monitoredQueue->Initialize());
- return monitoredQueue;
- } else {
- // TODO(crbug.com/335553337): support devices without fence.
- return DAWN_INTERNAL_ERROR("D3D11: fence is not supported");
+ auto queue = AcquireRef(new SystemEventQueue(device, descriptor));
+ DAWN_TRY(queue->Initialize());
+ return queue;
}
+
+ DAWN_ASSERT(deviceInfo.supportsMonitoredFence);
+ auto queue = AcquireRef(new MonitoredFenceQueue(device, descriptor));
+ DAWN_TRY(queue->Initialize());
+ return queue;
}
-MaybeError Queue::Initialize(bool isMonitored) {
+MaybeError Queue::Initialize(bool useNonMonitoredFence) {
if (!GetDevice()->IsToggleEnabled(Toggle::D3D11DisableFence)) {
- DAWN_TRY(InitializeD3DFence(isMonitored));
+ DAWN_TRY(InitializeD3DFence(useNonMonitoredFence));
}
return {};
}
-MaybeError Queue::InitializeD3DFence(bool isMonitored) {
+MaybeError Queue::InitializeD3DFence(bool useNonMonitoredFence) {
const auto& deviceInfo = ToBackend(GetDevice()->GetPhysicalDevice())->GetDeviceInfo();
// Create the fence.
D3D11_FENCE_FLAG flags = D3D11_FENCE_FLAG_SHARED;
- if (!isMonitored) {
+ if (useNonMonitoredFence) {
if (deviceInfo.supportsNonMonitoredFence) {
flags |= D3D11_FENCE_FLAG_NON_MONITORED;
// For adapters that support both monitored and non-monitored fences, non-monitored
@@ -134,7 +204,8 @@
}
DAWN_TRY(CheckHRESULT(
ToBackend(GetDevice())->GetD3D11Device5()->CreateFence(0, flags, IID_PPV_ARGS(&mFence)),
- isMonitored ? "D3D11: creating monitored fence" : "D3D11: creating non-monitored fence"));
+ useNonMonitoredFence ? "D3D11: creating non-monitored fence"
+ : "D3D11: creating monitored fence"));
DAWN_TRY_ASSIGN(mSharedFence, SharedFence::Create(ToBackend(GetDevice()),
"Internal shared DXGI fence", mFence));
@@ -312,12 +383,12 @@
return CheckPassedSerials();
}
-// MonitoredQueue:
-MaybeError MonitoredQueue::Initialize() {
- return Queue::Initialize(/*isMonitored=*/true);
+// MonitoredFenceQueue:
+MaybeError MonitoredFenceQueue::Initialize() {
+ return Queue::Initialize(/*useNonMonitoredFence=*/false);
}
-MaybeError MonitoredQueue::NextSerial() {
+MaybeError MonitoredFenceQueue::NextSerial() {
auto commandContext = GetScopedPendingCommandContext(SubmitMode::Passive);
DAWN_TRY(commandContext.FlushBuffersForSyncingWithCPU());
@@ -336,7 +407,7 @@
return {};
}
-ResultOrError<ExecutionSerial> MonitoredQueue::CheckAndUpdateCompletedSerials() {
+ResultOrError<ExecutionSerial> MonitoredFenceQueue::CheckAndUpdateCompletedSerials() {
ExecutionSerial completedSerial = ExecutionSerial(mFence->GetCompletedValue());
if (DAWN_UNLIKELY(completedSerial == ExecutionSerial(UINT64_MAX))) {
// GetCompletedValue returns UINT64_MAX if the device was removed.
@@ -359,13 +430,14 @@
return completedSerial;
}
-void MonitoredQueue::SetEventOnCompletion(ExecutionSerial serial, HANDLE event) {
+void MonitoredFenceQueue::SetEventOnCompletion(ExecutionSerial serial, HANDLE event) {
mFence->SetEventOnCompletion(static_cast<uint64_t>(serial), event);
}
// SystemEventQueue:
MaybeError SystemEventQueue::Initialize() {
- return Queue::Initialize(/*isMonitored=*/false);
+ return Queue::Initialize(
+ /*useNonMonitoredFence=*/GetDevice()->IsToggleEnabled(Toggle::D3D11UseUnmonitoredFence));
}
MaybeError SystemEventQueue::NextSerial() {
@@ -512,4 +584,201 @@
DAWN_UNREACHABLE();
}
+// DelayFlushQueue:
+MaybeError DelayFlushQueue::Initialize() {
+ return Queue::Initialize(
+ /*useNonMonitoredFence=*/GetDevice()->IsToggleEnabled(Toggle::D3D11UseUnmonitoredFence));
+}
+
+MaybeError DelayFlushQueue::NextSerial() {
+ auto commandContext = GetScopedPendingCommandContext(SubmitMode::Passive);
+
+ DAWN_TRY(commandContext.FlushBuffersForSyncingWithCPU());
+
+ ExecutionSerial submitSerial = GetPendingCommandSerial();
+
+ ComPtr<ID3D11Query> query;
+
+ if (!mFreeQueries.empty()) {
+ query = std::move(mFreeQueries.back());
+ mFreeQueries.pop_back();
+ } else {
+ D3D11_QUERY_DESC queryDesc = {};
+ queryDesc.Query = D3D11_QUERY_EVENT;
+ DAWN_TRY(
+ CheckHRESULT(ToBackend(GetDevice())->GetD3D11Device3()->CreateQuery(&queryDesc, &query),
+ "CreateQuery"));
+ }
+
+ commandContext.End(query.Get());
+
+ if (commandContext->AcquireNeedsFence()) {
+ DAWN_ASSERT(mFence);
+
+ TRACE_EVENT1(GetDevice()->GetPlatform(), General, "D3D11Device::SignalFence", "serial",
+ uint64_t(submitSerial));
+ DAWN_TRY(CheckHRESULT(commandContext.Signal(mFence.Get(), uint64_t(submitSerial)),
+ "D3D11 command queue signal fence"));
+ }
+
+ mPendingQueries.emplace_back(submitSerial, std::move(query));
+
+ IncrementLastSubmittedCommandSerial();
+
+ return {};
+}
+
+MaybeError DelayFlushQueue::CheckPendingQueries(
+ const ScopedCommandRecordingContext* commandContext) {
+ if (mPendingQueries.empty()) {
+ return {};
+ }
+
+ // Check queries' status starting from oldest to most recent.
+ // TODO(416736350): Consider using a binary search.
+ size_t completedQueriesCount = 0;
+ for (size_t i = 0; i < mPendingQueries.size(); ++i) {
+ bool done;
+ DAWN_TRY_ASSIGN(
+ done, IsQueryCompleted(commandContext, /*requireFlush=*/false, &mPendingQueries[i]));
+ if (!done) {
+ // We stop at 1st incompleted query.
+ break;
+ }
+ completedQueriesCount++;
+ }
+
+ if (completedQueriesCount == 0) {
+ return {};
+ }
+
+ MarkPendingQueriesAsComplete(completedQueriesCount);
+
+ return {};
+}
+
+ResultOrError<ExecutionSerial> DelayFlushQueue::CheckAndUpdateCompletedSerials() {
+ ExecutionSerial completedSerial;
+ {
+ auto commandContext = GetScopedPendingCommandContext(SubmitMode::Passive);
+
+ completedSerial = GetCompletedCommandSerial();
+
+ DAWN_TRY(CheckPendingQueries(&commandContext));
+
+ for (auto& e : mCompletedQueries) {
+ completedSerial = std::max(completedSerial, e.Serial());
+ mFreeQueries.emplace_back(e.AcquireQuery());
+ }
+ mCompletedQueries.clear();
+ }
+
+ // Finalize Mapping on ready buffers.
+ DAWN_TRY(CheckAndMapReadyBuffers(completedSerial));
+
+ return completedSerial;
+}
+
+ResultOrError<bool> DelayFlushQueue::WaitForQueueSerial(ExecutionSerial serial,
+ Nanoseconds timeout) {
+ ExecutionSerial completedSerial = GetCompletedCommandSerial();
+ if (serial <= completedSerial) {
+ return true;
+ }
+
+ if (serial > GetLastSubmittedCommandSerial()) {
+ return DAWN_FORMAT_INTERNAL_ERROR(
+ "Wait a serial (%llu) which is greater than last submitted command serial (%llu).",
+ uint64_t(serial), uint64_t(GetLastSubmittedCommandSerial()));
+ }
+
+ auto commandContext = GetScopedPendingCommandContext(SubmitMode::Passive);
+
+ DAWN_ASSERT(!mPendingQueries.empty());
+ DAWN_ASSERT(serial >= mPendingQueries.front().Serial());
+ DAWN_ASSERT(serial <= mPendingQueries.back().Serial());
+ auto it =
+ std::lower_bound(mPendingQueries.begin(), mPendingQueries.end(), serial,
+ [](const EventQuery& a, ExecutionSerial b) { return a.Serial() < b; });
+ DAWN_ASSERT(it != mPendingQueries.end());
+ DAWN_ASSERT(it->Serial() == serial);
+
+ bool done;
+ DAWN_TRY_ASSIGN(done, IsQueryCompleted(&commandContext, /*requireFlush=*/false, &(*it)));
+ if (timeout == Nanoseconds(0)) {
+ if (!done) {
+ // Return timed-out immediately without using a timer.
+ return false;
+ }
+ } else {
+ auto startTime = std::chrono::steady_clock::now();
+
+ while (!done) {
+ DAWN_TRY_ASSIGN(done, IsQueryCompleted(&commandContext, /*requireFlush=*/true, &(*it)));
+
+ if (!done) {
+ auto curTime = std::chrono::steady_clock::now();
+ auto elapsedNs =
+ std::chrono::duration_cast<std::chrono::nanoseconds>(curTime - startTime);
+ if (static_cast<uint64_t>(elapsedNs.count()) >= uint64_t(timeout)) {
+ return false;
+ }
+ std::this_thread::yield();
+ }
+ }
+ }
+
+ // Completed queries will be recycled in CheckAndUpdateCompletedSerials();
+ auto numCompletedQueries = std::distance(mPendingQueries.begin(), it) + 1;
+ MarkPendingQueriesAsComplete(numCompletedQueries);
+ return done;
+}
+
+void DelayFlushQueue::SetEventOnCompletion(ExecutionSerial serial, HANDLE event) {
+ DAWN_UNREACHABLE();
+}
+
+void DelayFlushQueue::MarkPendingQueriesAsComplete(size_t numCompletedQueries) {
+ mCompletedQueries.insert(
+ mCompletedQueries.end(), std::make_move_iterator(mPendingQueries.begin()),
+ std::make_move_iterator(mPendingQueries.begin() + numCompletedQueries));
+
+ mPendingQueries.erase(mPendingQueries.begin(), mPendingQueries.begin() + numCompletedQueries);
+}
+
+ResultOrError<bool> DelayFlushQueue::IsQueryCompleted(
+ const ScopedCommandRecordingContext* commandContext,
+ bool requireFlush,
+ EventQuery* eventQuery) {
+ BOOL done;
+
+ // If the GetData() calls count is 100 we will flush the commands. This is to avoid infinity
+ // loop when the application uses device.Tick() in a busy wait. The number 100 is arbitrarily
+ // chosen. It could be changed in future. Notes:
+ // - We shouldn't trigger flush eagerly when calls count < 100 because the the flush might be
+ // triggered externally via SwapChain's Present().
+ // - We don't need to trigger flush when calls count > 100 because any commands preceding this
+ // query should already be flushed when calls count is 100.
+ // - If the caller requires a flush, we only trigger flush if the calls count < 100.
+ // - TODO(416736350): Consider tracking last flush's serial so that we can skip the flush here
+ // if necessary.
+ constexpr size_t kFlushCheckpoint = 100;
+ if (requireFlush && eventQuery->checkCount < kFlushCheckpoint) {
+ eventQuery->checkCount = kFlushCheckpoint;
+ }
+
+ // Pass flag=0 if we want GetData() to flush the commands.
+ const UINT dontFlushFlag =
+ (eventQuery->checkCount == kFlushCheckpoint) ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH;
+ HRESULT hr =
+ commandContext->GetData(eventQuery->GetQuery(), &done, sizeof(done), dontFlushFlag);
+ DAWN_TRY(CheckHRESULT(hr, "GetQueryData()"));
+
+ eventQuery->checkCount++;
+
+ // A return value of S_FALSE means the query is not completed.
+ DAWN_ASSERT(hr == S_FALSE || done == TRUE);
+ return hr == S_OK;
+}
+
} // namespace dawn::native::d3d11
diff --git a/src/dawn/native/d3d11/QueueD3D11.h b/src/dawn/native/d3d11/QueueD3D11.h
index d04f171..40eef29 100644
--- a/src/dawn/native/d3d11/QueueD3D11.h
+++ b/src/dawn/native/d3d11/QueueD3D11.h
@@ -65,8 +65,8 @@
~Queue() override = default;
- MaybeError Initialize(bool isMonitored);
- MaybeError InitializeD3DFence(bool isMonitored);
+ MaybeError Initialize(bool useMonitoredFence);
+ MaybeError InitializeD3DFence(bool useMonitoredFence);
MaybeError SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) override;
MaybeError WriteBufferImpl(BufferBase* buffer,
diff --git a/src/dawn/tests/end2end/EventTests.cpp b/src/dawn/tests/end2end/EventTests.cpp
index 71633d7..c041a34 100644
--- a/src/dawn/tests/end2end/EventTests.cpp
+++ b/src/dawn/tests/end2end/EventTests.cpp
@@ -465,7 +465,8 @@
DAWN_INSTANTIATE_TEST_P(EventCompletionTests,
{D3D11Backend(), D3D11Backend({"d3d11_use_unmonitored_fence"}),
- D3D11Backend({"d3d11_disable_fence"}), D3D12Backend(), MetalBackend(),
+ D3D11Backend({"d3d11_disable_fence"}),
+ D3D11Backend({"d3d11_delay_flush_to_gpu"}), D3D12Backend(), MetalBackend(),
VulkanBackend(), OpenGLBackend(), OpenGLESBackend()},
{
WaitTypeAndCallbackMode::TimedWaitAny_WaitAnyOnly,
@@ -688,6 +689,7 @@
D3D11Backend(),
D3D11Backend({"d3d11_use_unmonitored_fence"}),
D3D11Backend({"d3d11_disable_fence"}),
+ D3D11Backend({"d3d11_delay_flush_to_gpu"}),
D3D12Backend(),
MetalBackend(),
VulkanBackend(),
@@ -715,6 +717,7 @@
D3D11Backend(),
D3D11Backend({"d3d11_use_unmonitored_fence"}),
D3D11Backend({"d3d11_disable_fence"}),
+ D3D11Backend({"d3d11_delay_flush_to_gpu"}),
D3D12Backend(),
MetalBackend(),
VulkanBackend(),
diff --git a/src/dawn/tests/end2end/QueueTests.cpp b/src/dawn/tests/end2end/QueueTests.cpp
index 3e983c9..ae1c93e 100644
--- a/src/dawn/tests/end2end/QueueTests.cpp
+++ b/src/dawn/tests/end2end/QueueTests.cpp
@@ -47,6 +47,7 @@
DAWN_INSTANTIATE_TEST(QueueTests,
D3D11Backend(),
+ D3D11Backend({"d3d11_delay_flush_to_gpu"}),
D3D12Backend(),
MetalBackend(),
NullBackend(),
@@ -266,6 +267,7 @@
DAWN_INSTANTIATE_TEST(QueueWriteBufferTests,
D3D11Backend(),
+ D3D11Backend({"d3d11_delay_flush_to_gpu"}),
D3D12Backend(),
MetalBackend(),
OpenGLBackend(),
@@ -786,7 +788,7 @@
}
DAWN_INSTANTIATE_TEST_P(QueueWriteTextureTests,
- {D3D11Backend(), D3D12Backend(),
+ {D3D11Backend(), D3D11Backend({"d3d11_delay_flush_to_gpu"}), D3D12Backend(),
D3D12Backend({"d3d12_use_temp_buffer_in_depth_stencil_texture_and_buffer_"
"copy_with_non_zero_buffer_offset"}),
MetalBackend(),
@@ -986,6 +988,7 @@
D3D11Backend(),
D3D11Backend({"d3d11_use_unmonitored_fence"}),
D3D11Backend({"d3d11_disable_fence"}),
+ D3D11Backend({"d3d11_delay_flush_to_gpu"}),
D3D12Backend(),
MetalBackend(),
OpenGLBackend(),
diff --git a/src/dawn/tests/end2end/SurfaceTests.cpp b/src/dawn/tests/end2end/SurfaceTests.cpp
index 93d6e87..3780107 100644
--- a/src/dawn/tests/end2end/SurfaceTests.cpp
+++ b/src/dawn/tests/end2end/SurfaceTests.cpp
@@ -657,6 +657,7 @@
DAWN_INSTANTIATE_TEST(SurfaceTests,
D3D11Backend(),
+ D3D11Backend({"d3d11_delay_flush_to_gpu"}),
D3D12Backend(),
MetalBackend(),
OpenGLBackend(),
diff --git a/src/dawn/tests/white_box/SharedTextureMemoryTests_win.cpp b/src/dawn/tests/white_box/SharedTextureMemoryTests_win.cpp
index 9eaddb2..d232e0d 100644
--- a/src/dawn/tests/white_box/SharedTextureMemoryTests_win.cpp
+++ b/src/dawn/tests/white_box/SharedTextureMemoryTests_win.cpp
@@ -581,8 +581,8 @@
DAWN_INSTANTIATE_PREFIXED_TEST_P(D3D,
SharedTextureMemoryTests,
- {D3D11Backend(), D3D11Backend({"d3d11_disable_fence"}),
- D3D12Backend()},
+ {D3D11Backend(), D3D11Backend({"d3d11_delay_flush_to_gpu"}),
+ D3D11Backend({"d3d11_disable_fence"}), D3D12Backend()},
{Backend::GetInstance<Mode::DXGISharedHandle>(),
Backend::GetKeyedMutexInstance<Mode::DXGISharedHandle>()},
{1});
@@ -597,7 +597,8 @@
DAWN_INSTANTIATE_PREFIXED_TEST_P(D3D11,
SharedTextureMemoryTests,
- {D3D11Backend(), D3D11Backend({"d3d11_disable_fence"})},
+ {D3D11Backend(), D3D11Backend({"d3d11_delay_flush_to_gpu"}),
+ D3D11Backend({"d3d11_disable_fence"})},
{Backend::GetInstance<Mode::D3D11Texture2D>(),
Backend::GetKeyedMutexInstance<Mode::D3D11Texture2D>(),
Backend::GetInstanceWithoutEndAccessFence()},
@@ -605,7 +606,9 @@
DAWN_INSTANTIATE_PREFIXED_TEST_P(D3D11,
SharedTextureMemoryWithFenceDisabledTests,
- {D3D11Backend({"d3d11_disable_fence"})},
+ {D3D11Backend({"d3d11_disable_fence"}),
+ D3D11Backend({"d3d11_disable_fence",
+ "d3d11_delay_flush_to_gpu"})},
{Backend::GetKeyedMutexInstance<Mode::DXGISharedHandle>()},
{1});