diff --git a/src/d3d11/d3d11_context_def.cpp b/src/d3d11/d3d11_context_def.cpp
index e2178a2f..988ccddb 100644
--- a/src/d3d11/d3d11_context_def.cpp
+++ b/src/d3d11/d3d11_context_def.cpp
@@ -80,10 +80,14 @@ namespace dxvk {
         m_queriesBegun.begin(),
         m_queriesBegun.end(), query);
 
-      if (unlikely(entry == m_queriesBegun.end()))
-        return;
-
-      m_queriesBegun.erase(entry);
+      if (likely(entry != m_queriesBegun.end())) {
+        m_queriesBegun.erase(entry);
+      } else {
+        EmitCs([cQuery = query]
+        (DxvkContext* ctx) {
+          cQuery->Begin(ctx);
+        });
+      }
     }
 
     m_commandList->AddQuery(query.ptr());
diff --git a/src/d3d11/d3d11_context_imm.cpp b/src/d3d11/d3d11_context_imm.cpp
index 0b4d9efa..a0a1f922 100644
--- a/src/d3d11/d3d11_context_imm.cpp
+++ b/src/d3d11/d3d11_context_imm.cpp
@@ -124,8 +124,12 @@ namespace dxvk {
     
     auto query = static_cast<D3D11Query*>(pAsync);
 
-    if (unlikely(!query->DoEnd()))
-      return;
+    if (unlikely(!query->DoEnd())) {
+      EmitCs([cQuery = Com<D3D11Query, false>(query)]
+      (DxvkContext* ctx) {
+        cQuery->Begin(ctx);
+      });
+    }
 
     EmitCs([cQuery = Com<D3D11Query, false>(query)]
     (DxvkContext* ctx) {
diff --git a/src/d3d11/d3d11_query.cpp b/src/d3d11/d3d11_query.cpp
index b35d9429..62a930d8 100644
--- a/src/d3d11/d3d11_query.cpp
+++ b/src/d3d11/d3d11_query.cpp
@@ -228,12 +228,14 @@ namespace dxvk {
   }
 
   bool STDMETHODCALLTYPE D3D11Query::DoEnd() {
-    if (IsScoped() && m_state != D3D11_VK_QUERY_BEGUN)
-      return false;
+    // Apparently the D3D11 runtime implicitly begins the query
+    // if it is in the wrong state at the time End is called, so
+    // let the caller react to it instead of just failing here.
+    bool result = m_state == D3D11_VK_QUERY_BEGUN || !IsScoped();
 
     m_state = D3D11_VK_QUERY_ENDED;
     m_resetCtr.fetch_add(1, std::memory_order_acquire);
-    return true;
+    return result;
   }