mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-05 01:24:14 +01:00
[util] Add helper class for common flush heuristic
This commit is contained in:
parent
741cc493c6
commit
0ac247c89c
@ -2,6 +2,7 @@ util_src = files([
|
|||||||
'util_env.cpp',
|
'util_env.cpp',
|
||||||
'util_string.cpp',
|
'util_string.cpp',
|
||||||
'util_fps_limiter.cpp',
|
'util_fps_limiter.cpp',
|
||||||
|
'util_flush.cpp',
|
||||||
'util_gdi.cpp',
|
'util_gdi.cpp',
|
||||||
'util_luid.cpp',
|
'util_luid.cpp',
|
||||||
'util_matrix.cpp',
|
'util_matrix.cpp',
|
||||||
|
79
src/util/util_flush.cpp
Normal file
79
src/util/util_flush.cpp
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#include "util_flush.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
bool GpuFlushTracker::considerFlush(
|
||||||
|
GpuFlushType flushType,
|
||||||
|
uint64_t chunkId,
|
||||||
|
uint32_t lastCompleteSubmissionId) {
|
||||||
|
constexpr uint32_t minPendingSubmissions = 2;
|
||||||
|
|
||||||
|
constexpr uint32_t minChunkCount = 3u;
|
||||||
|
constexpr uint32_t maxChunkCount = 20u;
|
||||||
|
|
||||||
|
// Do not flush if there is nothing to flush
|
||||||
|
uint32_t chunkCount = uint32_t(chunkId - m_lastFlushChunkId);
|
||||||
|
|
||||||
|
if (!chunkCount)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Take any earlier missed flush with a stronger hint into account, so
|
||||||
|
// that we still flush those as soon as possible. Ignore synchronization
|
||||||
|
// commands since they will either perform a flush or not need it at all.
|
||||||
|
flushType = std::min(flushType, m_lastMissedType);
|
||||||
|
|
||||||
|
if (flushType != GpuFlushType::ImplicitSynchronization)
|
||||||
|
m_lastMissedType = flushType;
|
||||||
|
|
||||||
|
switch (flushType) {
|
||||||
|
case GpuFlushType::ExplicitFlush: {
|
||||||
|
// This shouldn't really be called for explicit flushes,
|
||||||
|
// but handle them anyway for the sake of completeness
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case GpuFlushType::ImplicitStrongHint: {
|
||||||
|
// Flush aggressively with a strong hint to reduce readback latency.
|
||||||
|
return chunkCount >= minChunkCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
case GpuFlushType::ImplicitWeakHint: {
|
||||||
|
// Aim for a higher number of chunks per submission with
|
||||||
|
// a weak hint in order to avoid submitting too often.
|
||||||
|
if (chunkCount < 2 * minChunkCount)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Actual heuristic is shared with synchronization commands
|
||||||
|
} [[fallthrough]];
|
||||||
|
|
||||||
|
case GpuFlushType::ImplicitSynchronization: {
|
||||||
|
// If the GPU is about to go idle, flush aggressively. This may be
|
||||||
|
// required if the application is spinning on a query or resource.
|
||||||
|
uint32_t pendingSubmissions = uint32_t(m_lastFlushSubmissionId - lastCompleteSubmissionId);
|
||||||
|
|
||||||
|
if (pendingSubmissions < minPendingSubmissions)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Use the number of pending submissions to decide whether to flush. Other
|
||||||
|
// than ignoring the minimum chunk count condition, we should treat this
|
||||||
|
// the same as weak hints to avoid unnecessary synchronization.
|
||||||
|
uint32_t threshold = std::min(maxChunkCount, pendingSubmissions * minChunkCount);
|
||||||
|
return chunkCount >= threshold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should be unreachable
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GpuFlushTracker::notifyFlush(
|
||||||
|
uint64_t chunkId,
|
||||||
|
uint64_t submissionId) {
|
||||||
|
m_lastMissedType = GpuFlushType::ImplicitWeakHint;
|
||||||
|
|
||||||
|
m_lastFlushChunkId = chunkId;
|
||||||
|
m_lastFlushSubmissionId = submissionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
71
src/util/util_flush.h
Normal file
71
src/util/util_flush.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief GPU context flush type
|
||||||
|
*/
|
||||||
|
enum class GpuFlushType : uint32_t {
|
||||||
|
/** Flush or Present called by application */
|
||||||
|
ExplicitFlush = 0,
|
||||||
|
/** Function that requires GPU synchronization and
|
||||||
|
* may require a flush called by application */
|
||||||
|
ImplicitSynchronization = 1,
|
||||||
|
/** GPU command that applications are likely to synchronize
|
||||||
|
* with soon has been recorded into the command list */
|
||||||
|
ImplicitStrongHint = 2,
|
||||||
|
/** GPU commands have been recorded and a flush should be
|
||||||
|
* performed if the current command list is large enough. */
|
||||||
|
ImplicitWeakHint = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief GPU flush tracker
|
||||||
|
*
|
||||||
|
* Helper class that implements a context flush
|
||||||
|
* heuristic for various scenarios.
|
||||||
|
*/
|
||||||
|
class GpuFlushTracker {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Checks whether a context flush should be performed
|
||||||
|
*
|
||||||
|
* Note that this modifies internal state, and depending on the
|
||||||
|
* flush type, this may influence the decision for future flushes.
|
||||||
|
* \param [in] flushType Flush type
|
||||||
|
* \param [in] chunkId GPU command sequence number
|
||||||
|
* \param [in] lastCompleteSubmissionId Last completed command submission ID
|
||||||
|
* \returns \c true if a flush should be performed
|
||||||
|
*/
|
||||||
|
bool considerFlush(
|
||||||
|
GpuFlushType flushType,
|
||||||
|
uint64_t chunkId,
|
||||||
|
uint32_t lastCompleteSubmissionId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Notifies tracker about a context flush
|
||||||
|
*
|
||||||
|
* \param [in] chunkId GPU command sequence number
|
||||||
|
* \param [in] submissionId Command submission ID
|
||||||
|
*/
|
||||||
|
void notifyFlush(
|
||||||
|
uint64_t chunkId,
|
||||||
|
uint64_t submissionId);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
GpuFlushType m_lastMissedType = GpuFlushType::ImplicitWeakHint;
|
||||||
|
|
||||||
|
uint64_t m_lastFlushChunkId = 0ull;
|
||||||
|
uint64_t m_lastFlushSubmissionId = 0ull;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user