mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-12 13:08:50 +01:00
[dxvk] Accumulate query data into query object
And do so when adding additional query handles, in order to avoid allocating queries indefinitely if End is never called, which Halo:MCC supposedly does. Co-authored-by: Sam Edwards <CFSworks@gmail.com>
This commit is contained in:
parent
e430ff5cfd
commit
7f21a6c491
@ -28,7 +28,7 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
DxvkGpuQueryStatus DxvkGpuQuery::getData(DxvkQueryData& queryData) const {
|
||||
DxvkGpuQueryStatus DxvkGpuQuery::getData(DxvkQueryData& queryData) {
|
||||
queryData = DxvkQueryData();
|
||||
|
||||
// Callers must ensure that no begin call is pending when
|
||||
@ -37,21 +37,21 @@ namespace dxvk {
|
||||
if (!m_ended.load(std::memory_order_acquire))
|
||||
return DxvkGpuQueryStatus::Invalid;
|
||||
|
||||
// Get query data from all associated handles
|
||||
DxvkGpuQueryStatus status = DxvkGpuQueryStatus::Available;
|
||||
|
||||
for (size_t i = 0; i < m_handles.size()
|
||||
&& status == DxvkGpuQueryStatus::Available; i++)
|
||||
status = getDataForHandle(queryData, m_handles[i]);
|
||||
// Accumulate query data from all available queries
|
||||
DxvkGpuQueryStatus status = this->accumulateQueryData();
|
||||
|
||||
// Treat non-precise occlusion queries as available
|
||||
// if we already know the result will be non-zero
|
||||
if ((status == DxvkGpuQueryStatus::Pending)
|
||||
&& (m_type == VK_QUERY_TYPE_OCCLUSION)
|
||||
&& !(m_flags & VK_QUERY_CONTROL_PRECISE_BIT)
|
||||
&& (queryData.occlusion.samplesPassed))
|
||||
&& (m_queryData.occlusion.samplesPassed))
|
||||
status = DxvkGpuQueryStatus::Available;
|
||||
|
||||
|
||||
// Write back accumulated query data if the result is useful
|
||||
if (status == DxvkGpuQueryStatus::Available)
|
||||
queryData = m_queryData;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -61,10 +61,15 @@ namespace dxvk {
|
||||
// only the false->true transition is defined.
|
||||
m_ended.store(false, std::memory_order_relaxed);
|
||||
|
||||
// Ideally we should have no queries left at this point,
|
||||
// if we do, lifetime-track them with the command list.
|
||||
for (size_t i = 0; i < m_handles.size(); i++)
|
||||
cmd->trackGpuQuery(m_handles[i]);
|
||||
|
||||
m_handles.clear();
|
||||
|
||||
// Reset accumulated query data
|
||||
m_queryData = DxvkQueryData();
|
||||
}
|
||||
|
||||
|
||||
@ -75,14 +80,18 @@ namespace dxvk {
|
||||
|
||||
|
||||
void DxvkGpuQuery::addQueryHandle(const DxvkGpuQueryHandle& handle) {
|
||||
// Already accumulate available queries here in case
|
||||
// we already allocated a large number of queries
|
||||
if (m_handles.size() >= m_handles.MinCapacity)
|
||||
this->accumulateQueryData();
|
||||
|
||||
m_handles.push_back(handle);
|
||||
}
|
||||
|
||||
|
||||
DxvkGpuQueryStatus DxvkGpuQuery::getDataForHandle(
|
||||
DxvkQueryData& queryData,
|
||||
const DxvkGpuQueryHandle& handle) const {
|
||||
DxvkQueryData tmpData;
|
||||
DxvkGpuQueryStatus DxvkGpuQuery::accumulateQueryDataForHandle(
|
||||
const DxvkGpuQueryHandle& handle) {
|
||||
DxvkQueryData tmpData = { };
|
||||
|
||||
// Try to copy query data to temporary structure
|
||||
VkResult result = m_vkd->vkGetQueryPoolResults(m_vkd->device(),
|
||||
@ -98,30 +107,30 @@ namespace dxvk {
|
||||
// Add numbers to the destination structure
|
||||
switch (m_type) {
|
||||
case VK_QUERY_TYPE_OCCLUSION:
|
||||
queryData.occlusion.samplesPassed += tmpData.occlusion.samplesPassed;
|
||||
m_queryData.occlusion.samplesPassed += tmpData.occlusion.samplesPassed;
|
||||
break;
|
||||
|
||||
case VK_QUERY_TYPE_TIMESTAMP:
|
||||
queryData.timestamp.time = tmpData.timestamp.time;
|
||||
m_queryData.timestamp.time = tmpData.timestamp.time;
|
||||
break;
|
||||
|
||||
case VK_QUERY_TYPE_PIPELINE_STATISTICS:
|
||||
queryData.statistic.iaVertices += tmpData.statistic.iaVertices;
|
||||
queryData.statistic.iaPrimitives += tmpData.statistic.iaPrimitives;
|
||||
queryData.statistic.vsInvocations += tmpData.statistic.vsInvocations;
|
||||
queryData.statistic.gsInvocations += tmpData.statistic.gsInvocations;
|
||||
queryData.statistic.gsPrimitives += tmpData.statistic.gsPrimitives;
|
||||
queryData.statistic.clipInvocations += tmpData.statistic.clipInvocations;
|
||||
queryData.statistic.clipPrimitives += tmpData.statistic.clipPrimitives;
|
||||
queryData.statistic.fsInvocations += tmpData.statistic.fsInvocations;
|
||||
queryData.statistic.tcsPatches += tmpData.statistic.tcsPatches;
|
||||
queryData.statistic.tesInvocations += tmpData.statistic.tesInvocations;
|
||||
queryData.statistic.csInvocations += tmpData.statistic.csInvocations;
|
||||
m_queryData.statistic.iaVertices += tmpData.statistic.iaVertices;
|
||||
m_queryData.statistic.iaPrimitives += tmpData.statistic.iaPrimitives;
|
||||
m_queryData.statistic.vsInvocations += tmpData.statistic.vsInvocations;
|
||||
m_queryData.statistic.gsInvocations += tmpData.statistic.gsInvocations;
|
||||
m_queryData.statistic.gsPrimitives += tmpData.statistic.gsPrimitives;
|
||||
m_queryData.statistic.clipInvocations += tmpData.statistic.clipInvocations;
|
||||
m_queryData.statistic.clipPrimitives += tmpData.statistic.clipPrimitives;
|
||||
m_queryData.statistic.fsInvocations += tmpData.statistic.fsInvocations;
|
||||
m_queryData.statistic.tcsPatches += tmpData.statistic.tcsPatches;
|
||||
m_queryData.statistic.tesInvocations += tmpData.statistic.tesInvocations;
|
||||
m_queryData.statistic.csInvocations += tmpData.statistic.csInvocations;
|
||||
break;
|
||||
|
||||
case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT:
|
||||
queryData.xfbStream.primitivesWritten += tmpData.xfbStream.primitivesWritten;
|
||||
queryData.xfbStream.primitivesNeeded += tmpData.xfbStream.primitivesNeeded;
|
||||
m_queryData.xfbStream.primitivesWritten += tmpData.xfbStream.primitivesWritten;
|
||||
m_queryData.xfbStream.primitivesNeeded += tmpData.xfbStream.primitivesNeeded;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -131,6 +140,37 @@ namespace dxvk {
|
||||
|
||||
return DxvkGpuQueryStatus::Available;
|
||||
}
|
||||
|
||||
|
||||
DxvkGpuQueryStatus DxvkGpuQuery::accumulateQueryData() {
|
||||
DxvkGpuQueryStatus status = DxvkGpuQueryStatus::Available;
|
||||
|
||||
// Process available queries and return them to the
|
||||
// allocator if possible. This may help reduce the
|
||||
// number of Vulkan queries in flight.
|
||||
size_t queriesAvailable = 0;
|
||||
|
||||
while (queriesAvailable < m_handles.size()) {
|
||||
status = this->accumulateQueryDataForHandle(m_handles[queriesAvailable]);
|
||||
|
||||
if (status != DxvkGpuQueryStatus::Available)
|
||||
break;
|
||||
|
||||
queriesAvailable += 1;
|
||||
}
|
||||
|
||||
if (queriesAvailable) {
|
||||
for (size_t i = 0; i < queriesAvailable; i++)
|
||||
m_handles[i].allocator->freeQuery(m_handles[i]);
|
||||
|
||||
for (size_t i = queriesAvailable; i < m_handles.size(); i++)
|
||||
m_handles[i - queriesAvailable] = m_handles[i];
|
||||
|
||||
m_handles.resize(m_handles.size() - queriesAvailable);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -188,7 +188,7 @@ namespace dxvk {
|
||||
* \returns Current query status
|
||||
*/
|
||||
DxvkGpuQueryStatus getData(
|
||||
DxvkQueryData& queryData) const;
|
||||
DxvkQueryData& queryData);
|
||||
|
||||
/**
|
||||
* \brief Begins query
|
||||
@ -230,11 +230,14 @@ namespace dxvk {
|
||||
uint32_t m_index;
|
||||
std::atomic<bool> m_ended;
|
||||
|
||||
DxvkQueryData m_queryData = { };
|
||||
|
||||
small_vector<DxvkGpuQueryHandle, 8> m_handles;
|
||||
|
||||
DxvkGpuQueryStatus getDataForHandle(
|
||||
DxvkQueryData& queryData,
|
||||
const DxvkGpuQueryHandle& handle) const;
|
||||
DxvkGpuQueryStatus accumulateQueryDataForHandle(
|
||||
const DxvkGpuQueryHandle& handle);
|
||||
|
||||
DxvkGpuQueryStatus accumulateQueryData();
|
||||
|
||||
};
|
||||
|
||||
|
@ -9,6 +9,8 @@ namespace dxvk {
|
||||
using storage = std::aligned_storage_t<sizeof(T), alignof(T)>;
|
||||
public:
|
||||
|
||||
constexpr static size_t MinCapacity = N;
|
||||
|
||||
small_vector() { }
|
||||
|
||||
small_vector (const small_vector&) = delete;
|
||||
|
Loading…
Reference in New Issue
Block a user