diff --git a/src/dxvk/dxvk_gpu_query.cpp b/src/dxvk/dxvk_gpu_query.cpp index 426b58f6..7ceb32d1 100644 --- a/src/dxvk/dxvk_gpu_query.cpp +++ b/src/dxvk/dxvk_gpu_query.cpp @@ -18,11 +18,8 @@ namespace dxvk { DxvkGpuQuery::~DxvkGpuQuery() { - if (m_handle.queryPool) - m_handle.allocator->freeQuery(m_handle); - - for (DxvkGpuQueryHandle handle : m_handles) - handle.allocator->freeQuery(handle); + for (size_t i = 0; i < m_handles.size(); i++) + m_handles[i].allocator->freeQuery(m_handles[i]); } @@ -34,15 +31,14 @@ namespace dxvk { DxvkGpuQueryStatus DxvkGpuQuery::getData(DxvkQueryData& queryData) const { queryData = DxvkQueryData(); - if (!m_ended) + // Callers must ensure that no begin call is pending when + // calling this. Given that, once the query is ended, we + // know that no other thread will access query state. + if (!m_ended.load(std::memory_order_acquire)) 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 = DxvkGpuQueryStatus::Available; for (size_t i = 0; i < m_handles.size() && status == DxvkGpuQueryStatus::Available; i++) @@ -61,27 +57,25 @@ namespace dxvk { void DxvkGpuQuery::begin(const Rc& cmd) { - m_ended = false; + // Not useful to enforce a memory order here since + // only the false->true transition is defined. + m_ended.store(false, std::memory_order_relaxed); - cmd->trackGpuQuery(m_handle); - m_handle = DxvkGpuQueryHandle(); + for (size_t i = 0; i < m_handles.size(); i++) + cmd->trackGpuQuery(m_handles[i]); - for (const auto& handle : m_handles) - cmd->trackGpuQuery(handle); m_handles.clear(); } void DxvkGpuQuery::end() { - m_ended = true; + // Ensure that all prior writes are made available + m_ended.store(true, std::memory_order_release); } void DxvkGpuQuery::addQueryHandle(const DxvkGpuQueryHandle& handle) { - if (m_handle.queryPool) - m_handles.push_back(m_handle); - - m_handle = handle; + m_handles.push_back(handle); } diff --git a/src/dxvk/dxvk_gpu_query.h b/src/dxvk/dxvk_gpu_query.h index 0c45d120..f2318563 100644 --- a/src/dxvk/dxvk_gpu_query.h +++ b/src/dxvk/dxvk_gpu_query.h @@ -1,8 +1,11 @@ #pragma once +#include #include #include +#include "../util/util_small_vector.h" + #include "dxvk_resource.h" namespace dxvk { @@ -149,7 +152,10 @@ namespace dxvk { * \returns Current query handle */ DxvkGpuQueryHandle handle() const { - return m_handle; + if (m_handles.empty()) + return DxvkGpuQueryHandle(); + + return m_handles.back(); } /** @@ -222,11 +228,9 @@ namespace dxvk { VkQueryType m_type; VkQueryControlFlags m_flags; uint32_t m_index; - bool m_ended; + std::atomic m_ended; - DxvkGpuQueryHandle m_handle; - - std::vector m_handles; + small_vector m_handles; DxvkGpuQueryStatus getDataForHandle( DxvkQueryData& queryData, diff --git a/src/util/util_small_vector.h b/src/util/util_small_vector.h index 3302f1c5..13ff1ac7 100644 --- a/src/util/util_small_vector.h +++ b/src/util/util_small_vector.h @@ -90,6 +90,17 @@ namespace dxvk { ptr(--m_size)->~T(); } + void clear() { + for (size_t i = 0; i < m_size; i++) + ptr(i)->~T(); + + m_size = 0; + } + + bool empty() const { + return m_size == 0; + } + T& operator [] (size_t idx) { return *ptr(idx); } const T& operator [] (size_t idx) const { return *ptr(idx); }