diff --git a/src/dxvk/dxvk_cmdlist.cpp b/src/dxvk/dxvk_cmdlist.cpp index e3585e208..f4fe755f4 100644 --- a/src/dxvk/dxvk_cmdlist.cpp +++ b/src/dxvk/dxvk_cmdlist.cpp @@ -82,6 +82,7 @@ namespace dxvk { void DxvkCommandList::reset() { + m_queryTracker.reset(); m_stagingAlloc.reset(); m_descAlloc.reset(); m_resources.reset(); diff --git a/src/dxvk/dxvk_cmdlist.h b/src/dxvk/dxvk_cmdlist.h index 8447a593b..b449d72c9 100644 --- a/src/dxvk/dxvk_cmdlist.h +++ b/src/dxvk/dxvk_cmdlist.h @@ -7,7 +7,7 @@ #include "dxvk_lifetime.h" #include "dxvk_limits.h" #include "dxvk_pipelayout.h" -#include "dxvk_query_pool.h" +#include "dxvk_query_tracker.h" #include "dxvk_staging.h" namespace dxvk { @@ -81,8 +81,19 @@ namespace dxvk { * finished executing on the GPU. * \param [in] queries The query range */ - void trackQueryRange(const DxvkQueryRange& queries) { - m_queryRanges.push_back(queries); + void trackQueryRange(DxvkQueryRange&& queries) { + m_queryTracker.trackQueryRange(std::move(queries)); + } + + /** + * \brief Writes back query results + * + * Uses the query range to write back query data + * after the command list has finished executing + * on the GPU. + */ + void writeQueryData() { + m_queryTracker.writeQueryData(); } /** @@ -95,6 +106,7 @@ namespace dxvk { */ void reset(); + VkDescriptorSet allocateDescriptorSet( VkDescriptorSetLayout descriptorLayout) { return m_descAlloc.alloc(descriptorLayout); @@ -473,8 +485,7 @@ namespace dxvk { DxvkLifetimeTracker m_resources; DxvkDescriptorAlloc m_descAlloc; DxvkStagingAlloc m_stagingAlloc; - - std::vector m_queryRanges; + DxvkQueryTracker m_queryTracker; }; diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 243b27f6b..b415ed015 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -58,6 +58,10 @@ namespace dxvk { this->renderPassEnd(); this->endActiveQueries(); + this->trackQueryPool(m_queryPools[VK_QUERY_TYPE_OCCLUSION]); + this->trackQueryPool(m_queryPools[VK_QUERY_TYPE_PIPELINE_STATISTICS]); + this->trackQueryPool(m_queryPools[VK_QUERY_TYPE_TIMESTAMP]); + m_cmd->endRecording(); return std::exchange(m_cmd, nullptr); } @@ -1634,6 +1638,9 @@ namespace dxvk { queryHandle = queryPool->allocQuery(query); if (queryHandle.queryPool == VK_NULL_HANDLE) { + if (queryPool != nullptr) + this->trackQueryPool(queryPool); + m_queryPools[queryType] = m_device->createQueryPool(queryType, MaxNumQueryCountPerPool); queryPool = m_queryPools[queryType]; @@ -1652,6 +1659,16 @@ namespace dxvk { } + void DxvkContext::trackQueryPool(const Rc& pool) { + if (pool != nullptr) { + DxvkQueryRange range = pool->getActiveQueryRange(); + + if (range.queryCount > 0) + m_cmd->trackQueryRange(std::move(range)); + } + } + + void DxvkContext::beginActiveQueries() { for (const DxvkQueryRevision& query : m_activeQueries) { DxvkQueryHandle handle = this->allocQuery(query); diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 5ef47e905..0a4d04470 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -612,6 +612,9 @@ namespace dxvk { void resetQueryPool( const Rc& pool); + void trackQueryPool( + const Rc& pool); + void beginActiveQueries(); void endActiveQueries(); diff --git a/src/dxvk/dxvk_query_pool.cpp b/src/dxvk/dxvk_query_pool.cpp index 348af9819..31826ee62 100644 --- a/src/dxvk/dxvk_query_pool.cpp +++ b/src/dxvk/dxvk_query_pool.cpp @@ -91,4 +91,16 @@ namespace dxvk { m_queryRangeLength = 0; } + + DxvkQueryRange DxvkQueryPool::getActiveQueryRange() { + DxvkQueryRange result; + result.queryPool = this; + result.queryIndex = m_queryRangeOffset; + result.queryCount = m_queryRangeLength; + + m_queryRangeOffset += m_queryRangeLength; + m_queryRangeLength = 0; + return result; + } + } \ No newline at end of file diff --git a/src/dxvk/dxvk_query_pool.h b/src/dxvk/dxvk_query_pool.h index 826f6beaf..2c3110f7b 100644 --- a/src/dxvk/dxvk_query_pool.h +++ b/src/dxvk/dxvk_query_pool.h @@ -75,6 +75,16 @@ namespace dxvk { void reset( const Rc& cmd); + /** + * \brief Retrieves active query range + * + * This will also move the beginning of the + * new active query range to the end of the + * current active query range. + * \returns Active query range + */ + DxvkQueryRange getActiveQueryRange(); + private: Rc m_vkd; diff --git a/src/dxvk/dxvk_query_tracker.cpp b/src/dxvk/dxvk_query_tracker.cpp new file mode 100644 index 000000000..6a46747ea --- /dev/null +++ b/src/dxvk/dxvk_query_tracker.cpp @@ -0,0 +1,24 @@ +#include "dxvk_query_tracker.h" + +namespace dxvk { + + DxvkQueryTracker:: DxvkQueryTracker() { } + DxvkQueryTracker::~DxvkQueryTracker() { } + + + void DxvkQueryTracker::trackQueryRange(DxvkQueryRange&& queryRange) { + m_queries.push_back(std::move(queryRange)); + } + + + void DxvkQueryTracker::writeQueryData() { + for (const DxvkQueryRange& curr : m_queries) + curr.queryPool->getData(curr.queryIndex, curr.queryCount); + } + + + void DxvkQueryTracker::reset() { + m_queries.clear(); + } + +} \ No newline at end of file diff --git a/src/dxvk/dxvk_query_tracker.h b/src/dxvk/dxvk_query_tracker.h new file mode 100644 index 000000000..5ac9d24c8 --- /dev/null +++ b/src/dxvk/dxvk_query_tracker.h @@ -0,0 +1,45 @@ +#pragma once + +#include "dxvk_query_pool.h" + +namespace dxvk { + + /** + * \brief Query tracker + */ + class DxvkQueryTracker { + + public: + + DxvkQueryTracker(); + ~DxvkQueryTracker(); + + /** + * \brief Adds a query range to track + * \param [in] queryRange The query range + */ + void trackQueryRange(DxvkQueryRange&& queryRange); + + /** + * \brief Fetches query data + * + * Retrieves query data from the query pools + * and writes it back to the query objects. + */ + void writeQueryData(); + + /** + * \brief Resets query tracker + * + * Releases all query ranges from the tracker. + * Call this after writing back the query data. + */ + void reset(); + + private: + + std::vector m_queries; + + }; + +} \ No newline at end of file diff --git a/src/dxvk/dxvk_queue.cpp b/src/dxvk/dxvk_queue.cpp index 483f4f638..26a2fb953 100644 --- a/src/dxvk/dxvk_queue.cpp +++ b/src/dxvk/dxvk_queue.cpp @@ -56,6 +56,8 @@ namespace dxvk { if (entry.fence != nullptr) { entry.fence->wait(std::numeric_limits::max()); + + entry.cmdList->writeQueryData(); entry.cmdList->reset(); m_device->recycleCommandList(entry.cmdList); } diff --git a/src/dxvk/meson.build b/src/dxvk/meson.build index 0ceb16cca..2e1317a40 100644 --- a/src/dxvk/meson.build +++ b/src/dxvk/meson.build @@ -31,6 +31,7 @@ dxvk_src = files([ 'dxvk_pipemanager.cpp', 'dxvk_query.cpp', 'dxvk_query_pool.cpp', + 'dxvk_query_tracker.cpp', 'dxvk_queue.cpp', 'dxvk_renderpass.cpp', 'dxvk_resource.cpp',