diff --git a/src/dxvk/dxvk_gpu_query.cpp b/src/dxvk/dxvk_gpu_query.cpp index 426b58f6e70..df89b1a2c90 100644 --- a/src/dxvk/dxvk_gpu_query.cpp +++ b/src/dxvk/dxvk_gpu_query.cpp @@ -32,22 +32,12 @@ namespace dxvk { DxvkGpuQueryStatus DxvkGpuQuery::getData(DxvkQueryData& queryData) const { - queryData = DxvkQueryData(); - if (!m_ended) return DxvkGpuQueryStatus::Invalid; - - // Empty begin/end pair - if (!m_handle.queryPool) - return DxvkGpuQueryStatus::Available; - + // Get query data from all associated handles - DxvkGpuQueryStatus status = getDataForHandle(queryData, m_handle); + DxvkGpuQueryStatus status = flushHandles(); - for (size_t i = 0; i < m_handles.size() - && status == DxvkGpuQueryStatus::Available; i++) - status = getDataForHandle(queryData, m_handles[i]); - // Treat non-precise occlusion queries as available // if we already know the result will be non-zero if ((status == DxvkGpuQueryStatus::Pending) @@ -55,7 +45,10 @@ namespace dxvk { && !(m_flags & VK_QUERY_CONTROL_PRECISE_BIT) && (queryData.occlusion.samplesPassed)) status = DxvkGpuQueryStatus::Available; - + + if (status == DxvkGpuQueryStatus::Available) + queryData = m_queryData; + return status; } @@ -69,6 +62,8 @@ namespace dxvk { for (const auto& handle : m_handles) cmd->trackGpuQuery(handle); m_handles.clear(); + + m_queryData = DxvkQueryData(); } @@ -78,6 +73,11 @@ namespace dxvk { void DxvkGpuQuery::addQueryHandle(const DxvkGpuQueryHandle& handle) { + // Some apps forget to End() their queries; instead of accumulating query + // handles indefinitely, try to clean them up periodically. + if (m_handles.size() >= 256) + flushHandles(); + if (m_handle.queryPool) m_handles.push_back(m_handle); @@ -85,6 +85,32 @@ namespace dxvk { } + DxvkGpuQueryStatus DxvkGpuQuery::flushHandles() const { + // Consume handles in FIFO order, aggregating them into m_queryData + while (!m_handles.empty()) { + DxvkGpuQueryHandle handle = m_handles.front(); + + DxvkGpuQueryStatus status = getDataForHandle(m_queryData, handle); + if (status != DxvkGpuQueryStatus::Available) + return status; + + handle.allocator->freeQuery(handle); + m_handles.pop_front(); + } + + if (m_handle.queryPool) { + DxvkGpuQueryStatus status = getDataForHandle(m_queryData, m_handle); + if (status != DxvkGpuQueryStatus::Available) + return status; + + m_handle.allocator->freeQuery(m_handle); + m_handle = DxvkGpuQueryHandle(); + } + + return DxvkGpuQueryStatus::Available; + } + + DxvkGpuQueryStatus DxvkGpuQuery::getDataForHandle( DxvkQueryData& queryData, const DxvkGpuQueryHandle& handle) const { diff --git a/src/dxvk/dxvk_gpu_query.h b/src/dxvk/dxvk_gpu_query.h index 0c45d120006..482a7cf904a 100644 --- a/src/dxvk/dxvk_gpu_query.h +++ b/src/dxvk/dxvk_gpu_query.h @@ -224,10 +224,12 @@ namespace dxvk { uint32_t m_index; bool m_ended; - DxvkGpuQueryHandle m_handle; - - std::vector m_handles; - + mutable DxvkQueryData m_queryData; + mutable DxvkGpuQueryHandle m_handle; + mutable std::deque m_handles; + + DxvkGpuQueryStatus flushHandles() const; + DxvkGpuQueryStatus getDataForHandle( DxvkQueryData& queryData, const DxvkGpuQueryHandle& handle) const;