From a57dc752477c0401590776843f39c4be6bd21c3d Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 22 Jan 2020 04:17:13 +0100 Subject: [PATCH] [d3d11] Implicitly begin scoped queries in End if necessary Matches (undocumented) D3D11 behaviour. Warriors Orochi 4 runs into this because it does not begin some of its timestamp disjoint queries before ending them and retrieving data. --- src/d3d11/d3d11_context_def.cpp | 12 ++++++++---- src/d3d11/d3d11_context_imm.cpp | 8 ++++++-- src/d3d11/d3d11_query.cpp | 8 +++++--- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/d3d11/d3d11_context_def.cpp b/src/d3d11/d3d11_context_def.cpp index e2178a2f1a9..988ccddb869 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 0b4d9efa80f..a0a1f9229ce 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(pAsync); - if (unlikely(!query->DoEnd())) - return; + if (unlikely(!query->DoEnd())) { + EmitCs([cQuery = Com(query)] + (DxvkContext* ctx) { + cQuery->Begin(ctx); + }); + } EmitCs([cQuery = Com(query)] (DxvkContext* ctx) { diff --git a/src/d3d11/d3d11_query.cpp b/src/d3d11/d3d11_query.cpp index b35d9429e75..62a930d8989 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; }