// This code contains NVIDIA Confidential Information and is disclosed to you // under a form of NVIDIA software license agreement provided separately to you. // // Notice // NVIDIA Corporation and its licensors retain all intellectual property and // proprietary rights in and to this software and related documentation and // any modifications thereto. Any use, reproduction, disclosure, or // distribution of this software and related documentation without an express // license agreement from NVIDIA Corporation is strictly prohibited. // // ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES // NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO // THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, // MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. // // Information and code furnished is believed to be accurate and reliable. // However, NVIDIA Corporation assumes no responsibility for the consequences of use of such // information or for any infringement of patents or other rights of third parties that may // result from its use. No license is granted by implication or otherwise under any patent // or patent rights of NVIDIA Corporation. Details are subject to change without notice. // This code supersedes and replaces all information previously supplied. // NVIDIA Corporation products are not authorized for use as critical // components in life support devices or systems without express written approval of // NVIDIA Corporation. // // Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved. #if ENABLE_RENDER_TIMES #pragma once #include "Common.h" namespace GFSDK { namespace SSAO { //-------------------------------------------------------------------------------- enum GpuTimeRegimeIndex { REGIME_TIME_LINEAR_Z, REGIME_TIME_DEINTERLEAVE_Z, REGIME_TIME_NORMAL, REGIME_TIME_COARSE_AO, REGIME_TIME_INTERLEAVE_AO, REGIME_TIME_BLURX, REGIME_TIME_BLURY, REGIME_TIME_TOTAL, REGIME_TIME_COUNT }; struct RenderTimes { float GPUTimeMS[REGIME_TIME_COUNT]; }; #if SUPPORT_D3D11 namespace D3D11 { //-------------------------------------------------------------------------------- class TimestampQueries { public: void Create(ID3D11Device* pD3DDevice) { D3D11_QUERY_DESC queryDesc; queryDesc.MiscFlags = 0; queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT; SAFE_D3D_CALL( pD3DDevice->CreateQuery(&queryDesc, &m_pDisjointTimestampQuery) ); m_DisjointQueryInFlight = false; queryDesc.Query = D3D11_QUERY_TIMESTAMP; for (UINT i = 0; i < REGIME_TIME_COUNT; ++i) { SAFE_D3D_CALL( pD3DDevice->CreateQuery(&queryDesc, &m_pTimestampQueriesBegin[i]) ); SAFE_D3D_CALL( pD3DDevice->CreateQuery(&queryDesc, &m_pTimestampQueriesEnd[i]) ); m_TimestampQueryInFlight[i] = false; } } void Release() { SAFE_RELEASE(m_pDisjointTimestampQuery); for (UINT i = 0; i < REGIME_TIME_COUNT; ++i) { SAFE_RELEASE(m_pTimestampQueriesBegin[i]); SAFE_RELEASE(m_pTimestampQueriesEnd[i]); } } void Begin(ID3D11DeviceContext* pDeviceContext) { if (!m_DisjointQueryInFlight) { pDeviceContext->Begin(m_pDisjointTimestampQuery); } } void End(ID3D11DeviceContext* pDeviceContext, SSAO::RenderTimes* pRenderTimes) { if (!m_DisjointQueryInFlight) { pDeviceContext->End(m_pDisjointTimestampQuery); } m_DisjointQueryInFlight = true; D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjointTimestampValue; if (pDeviceContext->GetData(m_pDisjointTimestampQuery, &disjointTimestampValue, sizeof(disjointTimestampValue), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK) { m_DisjointQueryInFlight = false; if (!disjointTimestampValue.Disjoint) { double InvFrequencyMS = 1000.0 / disjointTimestampValue.Frequency; for (UINT i = 0; i < REGIME_TIME_COUNT; ++i) { if (m_TimestampQueryInFlight[i]) { UINT64 TimestampValueBegin; UINT64 TimestampValueEnd; if ((pDeviceContext->GetData(m_pTimestampQueriesBegin[i], &TimestampValueBegin, sizeof(UINT64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK) && (pDeviceContext->GetData(m_pTimestampQueriesEnd[i], &TimestampValueEnd, sizeof(UINT64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK)) { m_TimestampQueryInFlight[i] = false; pRenderTimes->GPUTimeMS[i] = float(double(TimestampValueEnd - TimestampValueBegin) * InvFrequencyMS); } } else { pRenderTimes->GPUTimeMS[i] = 0.f; } } } } } void StartTimer(ID3D11DeviceContext* pDeviceContext, GpuTimeRegimeIndex Id) { if (!m_TimestampQueryInFlight[Id]) { pDeviceContext->End(m_pTimestampQueriesBegin[Id]); } } void StopTimer(ID3D11DeviceContext* pDeviceContext, GpuTimeRegimeIndex Id) { if (!m_TimestampQueryInFlight[Id]) { pDeviceContext->End(m_pTimestampQueriesEnd[Id]); } m_TimestampQueryInFlight[Id] = true; } private: bool m_DisjointQueryInFlight; bool m_TimestampQueryInFlight[REGIME_TIME_COUNT]; ID3D11Query* m_pDisjointTimestampQuery; ID3D11Query* m_pTimestampQueriesBegin[REGIME_TIME_COUNT]; ID3D11Query* m_pTimestampQueriesEnd[REGIME_TIME_COUNT]; }; //-------------------------------------------------------------------------------- class GPUTimer { public: GPUTimer(TimestampQueries* pTimestampQueries, ID3D11DeviceContext* pDeviceContext, GpuTimeRegimeIndex Id) : m_pTimestampQueries(pTimestampQueries) , m_pDeviceContext(pDeviceContext) , m_GpuTimeRegimeIndex(Id) { m_pTimestampQueries->StartTimer(m_pDeviceContext, m_GpuTimeRegimeIndex); } ~GPUTimer() { m_pTimestampQueries->StopTimer(m_pDeviceContext, m_GpuTimeRegimeIndex); } private: TimestampQueries* m_pTimestampQueries; ID3D11DeviceContext* m_pDeviceContext; GpuTimeRegimeIndex m_GpuTimeRegimeIndex; }; #define GPU_TIMER_SCOPE(NAME) GPUTimer Timer(&m_TimestampQueries, pDeviceContext, GFSDK::SSAO::REGIME_TIME_ ## NAME) } //namespace D3D11 #endif //SUPPORT_D3D11 } // namespace SSAO } // namespace GFSDK #endif // ENABLE_RENDER_TIMES