1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-11 10:24:10 +01:00

[dxvk] Implement shared cache statistics

This commit is contained in:
Philip Rebohle 2024-09-24 23:40:17 +02:00 committed by Philip Rebohle
parent 2722a41675
commit 428b1087a0
4 changed files with 98 additions and 9 deletions

View File

@ -235,8 +235,9 @@ namespace dxvk {
} }
void DxvkDevice::getMemoryAllocationStats(DxvkMemoryAllocationStats& stats) { DxvkSharedAllocationCacheStats DxvkDevice::getMemoryAllocationStats(DxvkMemoryAllocationStats& stats) {
return m_objects.memoryManager().getAllocationStats(stats); m_objects.memoryManager().getAllocationStats(stats);
return m_objects.memoryManager().getAllocationCacheStats();
} }

View File

@ -408,8 +408,9 @@ namespace dxvk {
* *
* Expensive, should be used with caution. * Expensive, should be used with caution.
* \param [out] stats Allocation statistics * \param [out] stats Allocation statistics
* \returns Shared allocation cache stats
*/ */
void getMemoryAllocationStats(DxvkMemoryAllocationStats& stats); DxvkSharedAllocationCacheStats getMemoryAllocationStats(DxvkMemoryAllocationStats& stats);
/** /**
* \brief Retreves current frame ID * \brief Retreves current frame ID

View File

@ -286,14 +286,19 @@ namespace dxvk {
// If there's a list ready for us, take the whole thing // If there's a list ready for us, take the whole thing
std::unique_lock poolLock(m_poolMutex); std::unique_lock poolLock(m_poolMutex);
m_numRequests += 1u;
auto& pool = m_pools[poolIndex]; auto& pool = m_pools[poolIndex];
if (!pool.listCount) if (!pool.listCount) {
m_numMisses += 1u;
return nullptr; return nullptr;
}
if (!(--pool.listCount)) if (!(--pool.listCount))
pool.drainTime = high_resolution_clock::now(); pool.drainTime = high_resolution_clock::now();
m_cacheSize -= PoolCapacityInBytes;
return std::exchange(pool.lists[pool.listCount], nullptr); return std::exchange(pool.lists[pool.listCount], nullptr);
} }
@ -323,6 +328,10 @@ namespace dxvk {
if (likely(pool.listCount < PoolSize)) { if (likely(pool.listCount < PoolSize)) {
pool.lists[pool.listCount++] = allocation; pool.lists[pool.listCount++] = allocation;
if ((m_cacheSize += PoolCapacityInBytes) > m_maxCacheSize)
m_maxCacheSize = m_cacheSize;
return nullptr; return nullptr;
} }
@ -332,6 +341,21 @@ namespace dxvk {
} }
DxvkSharedAllocationCacheStats DxvkSharedAllocationCache::getStats() {
std::unique_lock poolLock(m_poolMutex);
DxvkSharedAllocationCacheStats result = { };
result.requestCount = m_numRequests;
result.missCount = m_numMisses;
result.size = m_maxCacheSize;
m_numRequests = 0u;
m_numMisses = 0u;
m_maxCacheSize = 0u;
return result;
}
void DxvkSharedAllocationCache::cleanupUnusedFromLockedAllocator( void DxvkSharedAllocationCache::cleanupUnusedFromLockedAllocator(
high_resolution_clock::time_point time) { high_resolution_clock::time_point time) {
std::unique_lock poolLock(m_poolMutex); std::unique_lock poolLock(m_poolMutex);
@ -1571,6 +1595,24 @@ namespace dxvk {
} }
DxvkSharedAllocationCacheStats DxvkMemoryAllocator::getAllocationCacheStats() const {
DxvkSharedAllocationCacheStats result = { };
for (uint32_t i = 0; i < m_memTypeCount; i++) {
const auto& type = m_memTypes[i];
if (type.sharedCache) {
DxvkSharedAllocationCacheStats stats = type.sharedCache->getStats();
result.requestCount += stats.requestCount;
result.missCount += stats.missCount;
result.size += stats.size;
}
}
return result;
}
bool DxvkMemoryAllocator::getBufferMemoryRequirements( bool DxvkMemoryAllocator::getBufferMemoryRequirements(
const VkBufferCreateInfo& createInfo, const VkBufferCreateInfo& createInfo,
VkMemoryRequirements2& memoryRequirements) const { VkMemoryRequirements2& memoryRequirements) const {

View File

@ -770,8 +770,6 @@ namespace dxvk {
* context classes in order to reduce lock contention. * context classes in order to reduce lock contention.
*/ */
class DxvkLocalAllocationCache { class DxvkLocalAllocationCache {
constexpr static VkDeviceSize PoolCapacityInBytes = 4u * DxvkPageAllocator::PageSize;
friend DxvkMemoryAllocator; friend DxvkMemoryAllocator;
public: public:
// Cache allocations up to 128 kiB // Cache allocations up to 128 kiB
@ -780,6 +778,8 @@ namespace dxvk {
constexpr static VkDeviceSize MinSize = DxvkPoolAllocator::MinSize; constexpr static VkDeviceSize MinSize = DxvkPoolAllocator::MinSize;
constexpr static VkDeviceSize MaxSize = MinSize << (PoolCount - 1u); constexpr static VkDeviceSize MaxSize = MinSize << (PoolCount - 1u);
constexpr static VkDeviceSize PoolCapacityInBytes = 4u * DxvkPageAllocator::PageSize;
DxvkLocalAllocationCache() = default; DxvkLocalAllocationCache() = default;
DxvkLocalAllocationCache( DxvkLocalAllocationCache(
@ -860,6 +860,22 @@ namespace dxvk {
}; };
/**
* \brief Allocation cache stats
*
* Keeps track of the number of requests as
* well as the total size of the cache.
*/
struct DxvkSharedAllocationCacheStats {
/// Total number of requests
uint32_t requestCount = 0u;
/// Number of failed requests
uint32_t missCount = 0u;
/// Cache size, in bytes
VkDeviceSize size = 0u;
};
/** /**
* \brief Shared allocation cache * \brief Shared allocation cache
* *
@ -870,6 +886,8 @@ namespace dxvk {
constexpr static uint32_t PoolCount = DxvkLocalAllocationCache::PoolCount; constexpr static uint32_t PoolCount = DxvkLocalAllocationCache::PoolCount;
constexpr static uint32_t PoolSize = env::is32BitHostPlatform() ? 6u : 12u; constexpr static uint32_t PoolSize = env::is32BitHostPlatform() ? 6u : 12u;
constexpr static VkDeviceSize PoolCapacityInBytes = DxvkLocalAllocationCache::PoolCapacityInBytes;
friend DxvkMemoryAllocator; friend DxvkMemoryAllocator;
public: public:
@ -898,6 +916,22 @@ namespace dxvk {
DxvkResourceAllocation* freeAllocation( DxvkResourceAllocation* freeAllocation(
DxvkResourceAllocation* allocation); DxvkResourceAllocation* allocation);
/**
* \brief Queries statistics
* \returns Cache statistics
*/
DxvkSharedAllocationCacheStats getStats();
/**
* \brief Frees unused memory
*
* Periodically called from the worker to free some
* memory that has not been used in some time.
* \param [in] time Current time
*/
void cleanupUnusedFromLockedAllocator(
high_resolution_clock::time_point time);
private: private:
struct FreeList { struct FreeList {
@ -923,8 +957,11 @@ namespace dxvk {
dxvk::mutex m_poolMutex; dxvk::mutex m_poolMutex;
std::array<Pool, PoolCount> m_pools = { }; std::array<Pool, PoolCount> m_pools = { };
void cleanupUnusedFromLockedAllocator( uint32_t m_numRequests = 0u;
high_resolution_clock::time_point time); uint32_t m_numMisses = 0u;
VkDeviceSize m_cacheSize = 0u;
VkDeviceSize m_maxCacheSize = 0u;
}; };
@ -1066,6 +1103,14 @@ namespace dxvk {
*/ */
void getAllocationStats(DxvkMemoryAllocationStats& stats); void getAllocationStats(DxvkMemoryAllocationStats& stats);
/**
* \brief Queries shared cache stats
*
* Returns statistics for all shared caches.
* \returns Shared cache stats
*/
DxvkSharedAllocationCacheStats getAllocationCacheStats() const;
/** /**
* \brief Queries buffer memory requirements * \brief Queries buffer memory requirements
* *