summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsTools
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2020-01-13 04:29:31 +0000
committerassiduous <assiduous@diligentgraphics.com>2020-01-13 04:29:31 +0000
commit5cfb2763ae0bd7a7eff679fa19565690be1abeb7 (patch)
tree0991b5944802b7040eb2ec16a70443a260d872ba /Graphics/GraphicsTools
parentVk query manager: improved query reuse order (diff)
downloadDiligentCore-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.txt2
-rw-r--r--Graphics/GraphicsTools/interface/DurationQueryHelper.h103
-rw-r--r--Graphics/GraphicsTools/src/DurationQueryHelper.cpp114
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