diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2020-01-13 04:29:31 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2020-01-13 04:29:31 +0000 |
| commit | 5cfb2763ae0bd7a7eff679fa19565690be1abeb7 (patch) | |
| tree | 0991b5944802b7040eb2ec16a70443a260d872ba /Graphics/GraphicsTools | |
| parent | Vk query manager: improved query reuse order (diff) | |
| download | DiligentCore-5cfb2763ae0bd7a7eff679fa19565690be1abeb7.tar.gz DiligentCore-5cfb2763ae0bd7a7eff679fa19565690be1abeb7.zip | |
Added DurationQueryHelper class; fixed issue with disjoint query in D3D11 backend
Diffstat (limited to 'Graphics/GraphicsTools')
| -rw-r--r-- | Graphics/GraphicsTools/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | Graphics/GraphicsTools/interface/DurationQueryHelper.h | 103 | ||||
| -rw-r--r-- | Graphics/GraphicsTools/src/DurationQueryHelper.cpp | 114 |
3 files changed, 219 insertions, 0 deletions
diff --git a/Graphics/GraphicsTools/CMakeLists.txt b/Graphics/GraphicsTools/CMakeLists.txt index 66b7a1ef..4c61df4b 100644 --- a/Graphics/GraphicsTools/CMakeLists.txt +++ b/Graphics/GraphicsTools/CMakeLists.txt @@ -4,6 +4,7 @@ project(Diligent-GraphicsTools CXX) set(INTERFACE interface/CommonlyUsedStates.h + interface/DurationQueryHelper.h interface/GraphicsUtilities.h interface/pch.h interface/ScopedQueryHelper.h @@ -14,6 +15,7 @@ set(INTERFACE ) set(SOURCE + src/DurationQueryHelper.cpp src/GraphicsUtilities.cpp src/ScopedQueryHelper.cpp src/ScreenCapture.cpp diff --git a/Graphics/GraphicsTools/interface/DurationQueryHelper.h b/Graphics/GraphicsTools/interface/DurationQueryHelper.h new file mode 100644 index 00000000..38c2325d --- /dev/null +++ b/Graphics/GraphicsTools/interface/DurationQueryHelper.h @@ -0,0 +1,103 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +#include <vector> +#include <deque> + +#include "../../GraphicsEngine/interface/RenderDevice.h" +#include "../../GraphicsEngine/interface/DeviceContext.h" +#include "../../GraphicsEngine/interface/Query.h" +#include "../../../Common/interface/RefCntAutoPtr.h" + +namespace Diligent +{ + +/// Helper class to manage duration queries. +/// One DurationQueryHelper instance must be used once per frame. +class DurationQueryHelper +{ +public: + DurationQueryHelper(IRenderDevice* pDevice, + Uint32 NumQueriesToReserve, + Uint32 ExpectedQueryLimit = 5); + + // clang-format off + DurationQueryHelper (const DurationQueryHelper&) = delete; + DurationQueryHelper& operator=(const DurationQueryHelper&) = delete; + DurationQueryHelper (DurationQueryHelper&&) = default; + DurationQueryHelper& operator=(DurationQueryHelper&&) = default; + // clang-format on + + + /// Begins a query. + + /// \param [in] pCtx - Context to record begin query command + /// + /// \remarks There must be exaclty one matching Begin() for every End() call, otherwise + /// the behavior is undefined. + void Begin(IDeviceContext* pCtx); + + + /// Ends a query and returns the duration, in seconds, if it is available. + + /// \param [in] pCtx - Context to record end query command. + /// \param [out] Duration - Variable where duration will be written to. + /// \return true if the data from the oldest query is available, and false otherwise. + /// + /// \remarks There must be exaclty one matching End() for every Begin() call, otherwise + /// the behavior is undefined. + bool End(IDeviceContext* pCtx, double& Duration); + +private: + RefCntAutoPtr<IRenderDevice> m_pDevice; + + const Uint32 m_ExpectedQueryLimit; + + struct DurationQuery + { + DurationQuery(IRenderDevice* pDevice); + + // clang-format off + DurationQuery (const DurationQuery&) = delete; + DurationQuery& operator=(const DurationQuery&) = delete; + DurationQuery (DurationQuery&&) = default; + DurationQuery& operator=(DurationQuery&&) = default; + // clang-format on + + RefCntAutoPtr<IQuery> StartTimestamp; + RefCntAutoPtr<IQuery> EndTimestamp; + }; + void InitDurationQuery(DurationQuery& query); + + + std::deque<DurationQuery> m_PendingQueries; + std::vector<DurationQuery> m_AvailableQueries; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsTools/src/DurationQueryHelper.cpp b/Graphics/GraphicsTools/src/DurationQueryHelper.cpp new file mode 100644 index 00000000..6f69bd0c --- /dev/null +++ b/Graphics/GraphicsTools/src/DurationQueryHelper.cpp @@ -0,0 +1,114 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "DurationQueryHelper.h" + +namespace Diligent +{ + +DurationQueryHelper::DurationQuery::DurationQuery(IRenderDevice* pDevice) +{ + QueryDesc queryDesc{QUERY_TYPE_TIMESTAMP}; + + queryDesc.Name = "Duration start timestamp query"; + pDevice->CreateQuery(queryDesc, &StartTimestamp); + VERIFY(StartTimestamp, "Failed to create start query"); + + queryDesc.Name = "Duration end timestamp query"; + pDevice->CreateQuery(queryDesc, &EndTimestamp); + VERIFY(EndTimestamp, "Failed to create end query"); +} + +DurationQueryHelper::DurationQueryHelper(IRenderDevice* pDevice, + Uint32 NumQueriesToReserve, + Uint32 ExpectedQueryLimit) : + m_pDevice{pDevice}, + m_ExpectedQueryLimit{ExpectedQueryLimit} +{ + m_AvailableQueries.reserve(NumQueriesToReserve); + for (Uint32 i = 0; i < NumQueriesToReserve; ++i) + { + m_AvailableQueries.emplace_back(pDevice); + } +} + +void DurationQueryHelper::Begin(IDeviceContext* pCtx) +{ + if (m_AvailableQueries.empty()) + { + m_AvailableQueries.emplace_back(m_pDevice); + } + + auto DurationQuery = std::move(m_AvailableQueries.back()); + m_AvailableQueries.pop_back(); + + pCtx->EndQuery(DurationQuery.StartTimestamp); + m_PendingQueries.push_front(std::move(DurationQuery)); +} + +bool DurationQueryHelper::End(IDeviceContext* pCtx, double& Duration) +{ + if (m_PendingQueries.empty()) + { + LOG_ERROR_MESSAGE("There are no pending queries, which likely indicates incosistent Begin()/End() calls"); + return false; + } + + if (m_PendingQueries.size() > m_ExpectedQueryLimit) + { + LOG_WARNING_MESSAGE("There are ", m_PendingQueries.size(), " pending queries which exceeds the specified expected limit (", m_ExpectedQueryLimit, ")"); + } + + pCtx->EndQuery(m_PendingQueries.front().EndTimestamp); + + auto& LastQuery = m_PendingQueries.back(); + + QueryDataTimestamp StartTimestampData; + + // Do not invalidate the query until we also get end timestamp + auto DataAvailable = LastQuery.StartTimestamp->GetData(&StartTimestampData, sizeof(StartTimestampData), false); + if (DataAvailable) + { + QueryDataTimestamp EndTimestampData; + DataAvailable = LastQuery.EndTimestamp->GetData(&EndTimestampData, sizeof(EndTimestampData)); + if (DataAvailable) + { + LastQuery.StartTimestamp->Invalidate(); + Duration = + static_cast<double>(EndTimestampData.Counter) / static_cast<double>(EndTimestampData.Frequency) - + static_cast<double>(StartTimestampData.Counter) / static_cast<double>(StartTimestampData.Frequency); + } + + m_AvailableQueries.emplace_back(std::move(LastQuery)); + m_PendingQueries.pop_back(); + } + + return DataAvailable; +} + +} // namespace Diligent |
