From 414fa5ee38e2055b41883fc9a8ecb42ec1483f6d Mon Sep 17 00:00:00 2001 From: assiduous Date: Mon, 24 Aug 2020 21:52:38 -0700 Subject: Implemented duration queries in D3D11 backend; added duration query test --- .../include/DeviceContextD3D11Impl.hpp | 2 + .../GraphicsEngineD3D11/include/QueryD3D11Impl.hpp | 7 +-- .../GraphicsEngineD3D11/interface/QueryD3D11.h | 13 ++++- .../src/DeviceContextD3D11Impl.cpp | 44 ++++++++++------ .../GraphicsEngineD3D11/src/QueryD3D11Impl.cpp | 58 +++++++++++++++++++--- 5 files changed, 98 insertions(+), 26 deletions(-) (limited to 'Graphics/GraphicsEngineD3D11') diff --git a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp index 53757b69..d2617152 100644 --- a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp @@ -318,6 +318,8 @@ private: void ClearStateCache(); + std::shared_ptr BeginDisjointQuery(); + CComPtr m_pd3d11DeviceContext; ///< D3D11 device context // clang-format off diff --git a/Graphics/GraphicsEngineD3D11/include/QueryD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/QueryD3D11Impl.hpp index 6cea3240..ece79c6a 100644 --- a/Graphics/GraphicsEngineD3D11/include/QueryD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/QueryD3D11Impl.hpp @@ -66,9 +66,10 @@ public: } /// Implementation of IQueryD3D11::GetD3D11Query(). - virtual ID3D11Query* DILIGENT_CALL_TYPE GetD3D11Query() override final + virtual ID3D11Query* DILIGENT_CALL_TYPE GetD3D11Query(Uint32 QueryId) override final { - return m_pd3d11Query; + VERIFY_EXPR(QueryId == 0 || m_Desc.Type == QUERY_TYPE_DURATION && QueryId == 1); + return m_pd3d11Query[QueryId]; } void SetDisjointQuery(std::shared_ptr DisjointQuery) @@ -77,7 +78,7 @@ public: } private: - CComPtr m_pd3d11Query; + CComPtr m_pd3d11Query[2]; std::shared_ptr m_DisjointQuery; }; diff --git a/Graphics/GraphicsEngineD3D11/interface/QueryD3D11.h b/Graphics/GraphicsEngineD3D11/interface/QueryD3D11.h index c9df1776..78180e02 100644 --- a/Graphics/GraphicsEngineD3D11/interface/QueryD3D11.h +++ b/Graphics/GraphicsEngineD3D11/interface/QueryD3D11.h @@ -45,19 +45,28 @@ static const struct INTERFACE_ID IID_QueryD3D11 = IQueryInclusiveMethods; \ IQueryD3D11Methods QueryD3D11 +// clang-format off + /// Exposes Direct3D11-specific functionality of a Query object. DILIGENT_BEGIN_INTERFACE(IQueryD3D11, IQuery) { /// Returns a pointer to the internal ID3D11Query object. - VIRTUAL ID3D11Query* METHOD(GetD3D11Query)(THIS) PURE; + /// \param [in] QueryId - Query Id. For most query types this must be 0. An exception is + /// QUERY_TYPE_DURATION, in which case allowed values are 0 for the + /// beginning timestamp query, and 1 for the ending query. + /// \return pointer to the ID3D11Query object. + VIRTUAL ID3D11Query* METHOD(GetD3D11Query)(THIS_ + Uint32 QueryId) PURE; }; DILIGENT_END_INTERFACE +// clang-format on + #include "../../../Primitives/interface/UndefInterfaceHelperMacros.h" #if DILIGENT_C_INTERFACE -# define IQueryD3D11_GetD3D11Query(This) CALL_IFACE_METHOD(QueryD3D11, GetD3D11Query, This) +# define IQueryD3D11_GetD3D11Query(This, ...) CALL_IFACE_METHOD(QueryD3D11, GetD3D11Query, This, __VA_ARGS__) #endif diff --git a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp index c94b0e03..17f2dd3a 100755 --- a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp @@ -1990,13 +1990,33 @@ void DeviceContextD3D11Impl::WaitForIdle() std::this_thread::yield(); } +std::shared_ptr DeviceContextD3D11Impl::BeginDisjointQuery() +{ + if (!m_ActiveDisjointQuery) + { + m_ActiveDisjointQuery = m_DisjointQueryPool.GetDisjointQuery(m_pDevice->GetD3D11Device()); + // Disjoint timestamp queries should only be invoked once per frame or less. + m_pd3d11DeviceContext->Begin(m_ActiveDisjointQuery->pd3d11Query); + m_ActiveDisjointQuery->IsEnded = false; + } + return m_ActiveDisjointQuery; +} + void DeviceContextD3D11Impl::BeginQuery(IQuery* pQuery) { if (!TDeviceContextBase::BeginQuery(pQuery, 0)) return; - auto* pQueryD3D11Impl = ValidatedCast(pQuery); - m_pd3d11DeviceContext->Begin(pQueryD3D11Impl->GetD3D11Query()); + auto* const pQueryD3D11Impl = ValidatedCast(pQuery); + if (pQueryD3D11Impl->GetDesc().Type == QUERY_TYPE_DURATION) + { + pQueryD3D11Impl->SetDisjointQuery(BeginDisjointQuery()); + m_pd3d11DeviceContext->End(pQueryD3D11Impl->GetD3D11Query(0)); + } + else + { + m_pd3d11DeviceContext->Begin(pQueryD3D11Impl->GetD3D11Query(0)); + } } void DeviceContextD3D11Impl::EndQuery(IQuery* pQuery) @@ -2004,20 +2024,16 @@ void DeviceContextD3D11Impl::EndQuery(IQuery* pQuery) if (!TDeviceContextBase::EndQuery(pQuery, 0)) return; - auto* pQueryD3D11Impl = ValidatedCast(pQuery); - if (pQueryD3D11Impl->GetDesc().Type == QUERY_TYPE_TIMESTAMP) + auto* const pQueryD3D11Impl = ValidatedCast(pQuery); + + const auto QueryType = pQueryD3D11Impl->GetDesc().Type; + VERIFY(QueryType != QUERY_TYPE_DURATION || m_ActiveDisjointQuery, + "There is no active disjoint query. Did you forget to call BeginQuery for the duration query?"); + if (QueryType == QUERY_TYPE_TIMESTAMP) { - if (!m_ActiveDisjointQuery) - { - m_ActiveDisjointQuery = m_DisjointQueryPool.GetDisjointQuery(m_pDevice->GetD3D11Device()); - // Disjoint timestamp queries should only be invoked once per frame or less. - m_pd3d11DeviceContext->Begin(m_ActiveDisjointQuery->pd3d11Query); - m_ActiveDisjointQuery->IsEnded = false; - } - pQueryD3D11Impl->SetDisjointQuery(m_ActiveDisjointQuery); + pQueryD3D11Impl->SetDisjointQuery(BeginDisjointQuery()); } - - m_pd3d11DeviceContext->End(pQueryD3D11Impl->GetD3D11Query()); + m_pd3d11DeviceContext->End(pQueryD3D11Impl->GetD3D11Query(QueryType == QUERY_TYPE_DURATION ? 1 : 0)); } void DeviceContextD3D11Impl::ClearStateCache() diff --git a/Graphics/GraphicsEngineD3D11/src/QueryD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/QueryD3D11Impl.cpp index bf70dfc1..e742958c 100644 --- a/Graphics/GraphicsEngineD3D11/src/QueryD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/QueryD3D11Impl.cpp @@ -53,6 +53,7 @@ QueryD3D11Impl::QueryD3D11Impl(IReferenceCounters* pRefCounters, break; case QUERY_TYPE_TIMESTAMP: + case QUERY_TYPE_DURATION: d3d11QueryDesc.Query = D3D11_QUERY_TIMESTAMP; break; @@ -65,9 +66,12 @@ QueryD3D11Impl::QueryD3D11Impl(IReferenceCounters* pRefCounters, } auto* pd3d11Device = pDevice->GetD3D11Device(); - auto hr = pd3d11Device->CreateQuery(&d3d11QueryDesc, &m_pd3d11Query); - CHECK_D3D_RESULT_THROW(hr, "Failed to create D3D11 query object"); - VERIFY_EXPR(m_pd3d11Query != nullptr); + for (Uint32 i = 0; i < (Desc.Type == QUERY_TYPE_DURATION ? Uint32{2} : Uint32{1}); ++i) + { + auto hr = pd3d11Device->CreateQuery(&d3d11QueryDesc, &m_pd3d11Query[i]); + CHECK_D3D_RESULT_THROW(hr, "Failed to create D3D11 query object"); + VERIFY_EXPR(m_pd3d11Query[i] != nullptr); + } } QueryD3D11Impl::~QueryD3D11Impl() @@ -90,7 +94,7 @@ bool QueryD3D11Impl::GetData(void* pData, Uint32 DataSize, bool AutoInvalidate) case QUERY_TYPE_OCCLUSION: { UINT64 NumSamples; - DataReady = pd3d11Ctx->GetData(m_pd3d11Query, &NumSamples, sizeof(NumSamples), 0) == S_OK; + DataReady = pd3d11Ctx->GetData(m_pd3d11Query[0], &NumSamples, sizeof(NumSamples), 0) == S_OK; if (DataReady && pData != nullptr) { auto& QueryData = *reinterpret_cast(pData); @@ -102,7 +106,7 @@ bool QueryD3D11Impl::GetData(void* pData, Uint32 DataSize, bool AutoInvalidate) case QUERY_TYPE_BINARY_OCCLUSION: { BOOL AnySamplePassed; - DataReady = pd3d11Ctx->GetData(m_pd3d11Query, &AnySamplePassed, sizeof(AnySamplePassed), 0) == S_OK; + DataReady = pd3d11Ctx->GetData(m_pd3d11Query[0], &AnySamplePassed, sizeof(AnySamplePassed), 0) == S_OK; if (DataReady && pData != nullptr) { auto& QueryData = *reinterpret_cast(pData); @@ -123,8 +127,9 @@ bool QueryD3D11Impl::GetData(void* pData, Uint32 DataSize, bool AutoInvalidate) if (DataReady) { UINT64 Counter = 0; - DataReady = pd3d11Ctx->GetData(m_pd3d11Query, &Counter, sizeof(Counter), 0) == S_OK; + DataReady = pd3d11Ctx->GetData(m_pd3d11Query[0], &Counter, sizeof(Counter), 0) == S_OK; + // Note: DataReady is a return value, so we query the counter first, and then check pData for null. if (DataReady && pData != nullptr) { D3D11_QUERY_DATA_TIMESTAMP_DISJOINT DisjointQueryData; @@ -145,7 +150,7 @@ bool QueryD3D11Impl::GetData(void* pData, Uint32 DataSize, bool AutoInvalidate) case QUERY_TYPE_PIPELINE_STATISTICS: { D3D11_QUERY_DATA_PIPELINE_STATISTICS d3d11QueryData; - DataReady = pd3d11Ctx->GetData(m_pd3d11Query, &d3d11QueryData, sizeof(d3d11QueryData), 0) == S_OK; + DataReady = pd3d11Ctx->GetData(m_pd3d11Query[0], &d3d11QueryData, sizeof(d3d11QueryData), 0) == S_OK; if (DataReady && pData != nullptr) { auto& QueryData = *reinterpret_cast(pData); @@ -165,6 +170,45 @@ bool QueryD3D11Impl::GetData(void* pData, Uint32 DataSize, bool AutoInvalidate) } break; + case QUERY_TYPE_DURATION: + { + // Timestamp query is only useful if two timestamp queries are done in the middle of a D3D11_QUERY_TIMESTAMP_DISJOINT query. + // Timestamp disjoint query is begun by the device context when the first timestamp query is begun and ended + // by FinishFrame. Thus timestamp queries will only become available after FinishFrame. + + VERIFY_EXPR(m_DisjointQuery); + + DataReady = m_DisjointQuery->IsEnded; + if (DataReady) + { + UINT64 StartCounter = 0; + UINT64 EndCounter = 0; + + DataReady = pd3d11Ctx->GetData(m_pd3d11Query[0], &StartCounter, sizeof(StartCounter), 0) == S_OK; + if (DataReady) + { + DataReady = pd3d11Ctx->GetData(m_pd3d11Query[1], &EndCounter, sizeof(EndCounter), 0) == S_OK; + + // Note: DataReady is a return value, so we query the counters first, and then check pData for null. + if (DataReady && pData != nullptr) + { + D3D11_QUERY_DATA_TIMESTAMP_DISJOINT DisjointQueryData; + DataReady = pd3d11Ctx->GetData(m_DisjointQuery->pd3d11Query, &DisjointQueryData, sizeof(DisjointQueryData), 0) == S_OK; + + if (DataReady) + { + auto& QueryData = *reinterpret_cast(pData); + VERIFY_EXPR(EndCounter >= StartCounter); + QueryData.Duration = EndCounter - StartCounter; + // The timestamp returned by ID3D11DeviceContext::GetData for a timestamp query is only reliable if Disjoint is FALSE. + QueryData.Frequency = DisjointQueryData.Disjoint ? 0 : DisjointQueryData.Frequency; + } + } + } + } + } + break; + default: UNEXPECTED("Unexpected query type"); } -- cgit v1.2.3