[dxvk] Adjust desciptor pool reset heuristic

Drastically limits the amount of descriptor memory we allocate in situations
where an application renders without presenting anything to a swap chain.

The new limit is a bit tight for some real-world use cases (e.g. Ashes of the Singularity),
but at worst we will start calling vkAllocateDescriptorSets once per set and draw.
This commit is contained in:
Philip Rebohle 2024-04-08 15:40:25 +02:00
parent 49e9ea5f5a
commit 44695f9311
2 changed files with 10 additions and 17 deletions

View File

@ -72,7 +72,7 @@ namespace dxvk {
// memory bloat. This may be necessary for off-screen
// rendering applications, or in situations where games
// pre-render a lot of images without presenting in between.
return m_descriptorPools.size() >= 8;
return m_descriptorPools.size() > MaxDesiredPoolCount;
}
@ -100,29 +100,25 @@ namespace dxvk {
void DxvkDescriptorPool::reset() {
// As a heuristic to save memory, check how many descriptors
// have actively been used in the past couple of submissions.
bool isLowUsageFrame = false;
// As a heuristic to save memory, check how many descriptor
// sets were actually being used in past submissions.
size_t poolCount = m_descriptorPools.size();
bool needsReset = poolCount > MaxDesiredPoolCount;
if (poolCount > 1 || m_setsAllocated > m_manager->getMaxSetCount() / 2) {
double factor = std::max(11.0 / 3.0 - double(poolCount) / 3.0, 1.0);
isLowUsageFrame = double(m_setsUsed) * factor < double(m_setsAllocated);
needsReset = double(m_setsUsed) * factor < double(m_setsAllocated);
}
m_lowUsageFrames = isLowUsageFrame
? m_lowUsageFrames + 1
: 0;
m_setsUsed = 0;
if (m_lowUsageFrames < 16) {
if (!needsReset) {
for (auto& entry : m_setLists)
entry.second.reset();
} else {
// If most sets are no longer being used, reset and destroy
// descriptor pools and reset all lookup tables in order to
// accomodate more descriptors of different layouts.
// If most sets are no longer needed, reset and destroy
// descriptor pools and reset all lookup tables in order
// to accomodate more descriptors of different layouts.
for (auto pool : m_descriptorPools)
m_manager->recycleVulkanDescriptorPool(pool);
@ -131,7 +127,6 @@ namespace dxvk {
m_setMaps.clear();
m_setsAllocated = 0;
m_lowUsageFrames = 0;
}
m_cachedEntry = { nullptr, nullptr };

View File

@ -80,7 +80,7 @@ namespace dxvk {
* to be updated.
*/
class DxvkDescriptorPool : public RcObject {
constexpr static uint32_t MaxDesiredPoolCount = 2;
public:
DxvkDescriptorPool(
@ -155,8 +155,6 @@ namespace dxvk {
uint32_t m_prevSetsAllocated = 0;
uint32_t m_lowUsageFrames = 0;
DxvkDescriptorSetMap* getSetMapCached(
const DxvkBindingLayoutObjects* layout);