diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2020-08-25 04:52:38 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2020-08-25 04:52:38 +0000 |
| commit | 414fa5ee38e2055b41883fc9a8ecb42ec1483f6d (patch) | |
| tree | dedddbea70658e301d06efc401eaabfc35e24920 /Graphics/GraphicsEngineD3D11 | |
| parent | Added QUERY_TYPE_DURATION value and QueryDataDuration struct (diff) | |
| download | DiligentCore-414fa5ee38e2055b41883fc9a8ecb42ec1483f6d.tar.gz DiligentCore-414fa5ee38e2055b41883fc9a8ecb42ec1483f6d.zip | |
Implemented duration queries in D3D11 backend; added duration query test
Diffstat (limited to 'Graphics/GraphicsEngineD3D11')
5 files changed, 98 insertions, 26 deletions
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<DisjointQueryPool::DisjointQueryWrapper> BeginDisjointQuery(); + CComPtr<ID3D11DeviceContext> 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<DisjointQueryPool::DisjointQueryWrapper> DisjointQuery) @@ -77,7 +78,7 @@ public: } private: - CComPtr<ID3D11Query> m_pd3d11Query; + CComPtr<ID3D11Query> m_pd3d11Query[2]; std::shared_ptr<DisjointQueryPool::DisjointQueryWrapper> 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<DisjointQueryPool::DisjointQueryWrapper> 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<QueryD3D11Impl>(pQuery);
- m_pd3d11DeviceContext->Begin(pQueryD3D11Impl->GetD3D11Query());
+ auto* const pQueryD3D11Impl = ValidatedCast<QueryD3D11Impl>(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<QueryD3D11Impl>(pQuery);
- if (pQueryD3D11Impl->GetDesc().Type == QUERY_TYPE_TIMESTAMP)
+ auto* const pQueryD3D11Impl = ValidatedCast<QueryD3D11Impl>(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<QueryDataOcclusion*>(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<QueryDataBinaryOcclusion*>(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<QueryDataPipelineStatistics*>(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<QueryDataDuration*>(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"); } |
