Commit 2663e601 by Tim Van Patten Committed by Commit Bot

Vulkan: Dynamically grow descriptor pool sizes

Initial testing using benchmarks shows that the majority of the descriptor pools allocate fewer than 32 descriptor sets worth of descriptors. This CL reduces the initial size of each pool from 128 to 32 to reduce memory consumption. Additionally, when a pool is exhausted and a new one is created, the size of the pool doubles each time, up to a max of 512 descriptor sets worth of descriptors. This allows us to aggressively increase the size of the pools that appear to be very hot and decrease the total number of pools created. Bug: angleproject:5067 Test: CQ Change-Id: I190059cf04134902d6251d475dd908c1cbb82b58 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2430193Reviewed-by: 's avatarCharlie Lao <cclao@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Tim Van Patten <timvp@google.com>
parent 6612da1f
......@@ -562,7 +562,8 @@ bool IsShaderReadOnlyLayout(const ImageMemoryBarrierData &imageLayout)
} // anonymous namespace
// This is an arbitrary max. We can change this later if necessary.
uint32_t DynamicDescriptorPool::mMaxSetsPerPool = 128;
uint32_t DynamicDescriptorPool::mMaxSetsPerPool = 16;
uint32_t DynamicDescriptorPool::mMaxSetsPerPoolMultiplier = 2;
VkImageLayout ConvertImageLayoutToVkImageLayout(ImageLayout imageLayout)
{
......@@ -1674,7 +1675,7 @@ bool DescriptorPoolHelper::hasCapacity(uint32_t descriptorSetCount) const
}
angle::Result DescriptorPoolHelper::init(ContextVk *contextVk,
const std::vector<VkDescriptorPoolSize> &poolSizes,
const std::vector<VkDescriptorPoolSize> &poolSizesIn,
uint32_t maxSets)
{
if (mDescriptorPool.valid())
......@@ -1683,6 +1684,14 @@ angle::Result DescriptorPoolHelper::init(ContextVk *contextVk,
mDescriptorPool.destroy(contextVk->getDevice());
}
// Make a copy of the pool sizes, so we can grow them to satisfy the specified maxSets.
std::vector<VkDescriptorPoolSize> poolSizes = poolSizesIn;
for (VkDescriptorPoolSize &poolSize : poolSizes)
{
poolSize.descriptorCount *= maxSets;
}
VkDescriptorPoolCreateInfo descriptorPoolInfo = {};
descriptorPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
descriptorPoolInfo.flags = 0;
......@@ -1748,11 +1757,6 @@ angle::Result DynamicDescriptorPool::init(ContextVk *contextVk,
ASSERT(mCachedDescriptorSetLayout == VK_NULL_HANDLE);
mPoolSizes.assign(setSizes, setSizes + setSizeCount);
for (uint32_t i = 0; i < setSizeCount; ++i)
{
mPoolSizes[i].descriptorCount *= mMaxSetsPerPool;
}
mCachedDescriptorSetLayout = descriptorSetLayout;
mDescriptorPools.push_back(new RefCountedDescriptorPoolHelper());
......@@ -1847,19 +1851,40 @@ angle::Result DynamicDescriptorPool::allocateNewPool(ContextVk *contextVk)
ANGLE_VK_CHECK(contextVk, mDescriptorPools.size() < kMaxPools, VK_ERROR_TOO_MANY_OBJECTS);
}
// This pool is getting hot, so grow its max size to try and prevent allocating another pool in
// the future.
if (mMaxSetsPerPool < KMaxSetsPerPoolMax)
{
mMaxSetsPerPool *= mMaxSetsPerPoolMultiplier;
}
return mDescriptorPools[mCurrentPoolIndex]->get().init(contextVk, mPoolSizes, mMaxSetsPerPool);
}
// For testing only!
uint32_t DynamicDescriptorPool::GetMaxSetsPerPoolForTesting()
{
return mMaxSetsPerPool;
}
// For testing only!
void DynamicDescriptorPool::SetMaxSetsPerPoolForTesting(uint32_t maxSetsPerPool)
{
mMaxSetsPerPool = maxSetsPerPool;
}
// For testing only!
uint32_t DynamicDescriptorPool::GetMaxSetsPerPoolMultiplierForTesting()
{
return mMaxSetsPerPoolMultiplier;
}
// For testing only!
void DynamicDescriptorPool::SetMaxSetsPerPoolMultiplierForTesting(uint32_t maxSetsPerPoolMultiplier)
{
mMaxSetsPerPoolMultiplier = maxSetsPerPoolMultiplier;
}
// DynamicallyGrowingPool implementation
template <typename Pool>
DynamicallyGrowingPool<Pool>::DynamicallyGrowingPool()
......
......@@ -253,7 +253,7 @@ class DescriptorPoolHelper
bool hasCapacity(uint32_t descriptorSetCount) const;
angle::Result init(ContextVk *contextVk,
const std::vector<VkDescriptorPoolSize> &poolSizes,
const std::vector<VkDescriptorPoolSize> &poolSizesIn,
uint32_t maxSets);
void destroy(VkDevice device);
void release(ContextVk *contextVk);
......@@ -317,11 +317,15 @@ class DynamicDescriptorPool final : angle::NonCopyable
// For testing only!
static uint32_t GetMaxSetsPerPoolForTesting();
static void SetMaxSetsPerPoolForTesting(uint32_t maxSetsPerPool);
static uint32_t GetMaxSetsPerPoolMultiplierForTesting();
static void SetMaxSetsPerPoolMultiplierForTesting(uint32_t maxSetsPerPool);
private:
angle::Result allocateNewPool(ContextVk *contextVk);
static constexpr uint32_t KMaxSetsPerPoolMax = 512;
static uint32_t mMaxSetsPerPool;
static uint32_t mMaxSetsPerPoolMultiplier;
size_t mCurrentPoolIndex;
std::vector<RefCountedDescriptorPoolHelper *> mDescriptorPools;
std::vector<VkDescriptorPoolSize> mPoolSizes;
......
......@@ -29,22 +29,30 @@ class VulkanDescriptorSetTest : public ANGLETest
void testSetUp() override
{
mMaxSetsPerPool = rx::vk::DynamicDescriptorPool::GetMaxSetsPerPoolForTesting();
mMaxSetsPerPoolMultiplier =
rx::vk::DynamicDescriptorPool::GetMaxSetsPerPoolMultiplierForTesting();
}
void testTearDown() override
{
rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolForTesting(mMaxSetsPerPool);
rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolMultiplierForTesting(
mMaxSetsPerPoolMultiplier);
}
static constexpr uint32_t kMaxSetsForTesting = 1;
static constexpr uint32_t kMaxSetsForTesting = 1;
static constexpr uint32_t kMaxSetsMultiplierForTesting = 1;
void limitMaxSets()
{
rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolForTesting(kMaxSetsForTesting);
rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolMultiplierForTesting(
kMaxSetsMultiplierForTesting);
}
private:
uint32_t mMaxSetsPerPool;
uint32_t mMaxSetsPerPoolMultiplier;
};
// Test atomic counter read.
......
......@@ -41,11 +41,15 @@ class VulkanUniformUpdatesTest : public ANGLETest
mLastContext = getEGLWindow()->getContext();
mMaxSetsPerPool = rx::vk::DynamicDescriptorPool::GetMaxSetsPerPoolForTesting();
mMaxSetsPerPoolMultiplier =
rx::vk::DynamicDescriptorPool::GetMaxSetsPerPoolMultiplierForTesting();
}
void testTearDown() override
{
rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolForTesting(mMaxSetsPerPool);
rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolMultiplierForTesting(
mMaxSetsPerPoolMultiplier);
}
rx::ContextVk *hackANGLE() const
......@@ -63,11 +67,14 @@ class VulkanUniformUpdatesTest : public ANGLETest
return rx::vk::GetImpl(texture);
}
static constexpr uint32_t kMaxSetsForTesting = 1;
static constexpr uint32_t kMaxSetsForTesting = 1;
static constexpr uint32_t kMaxSetsMultiplierForTesting = 1;
void limitMaxSets()
{
rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolForTesting(kMaxSetsForTesting);
rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolMultiplierForTesting(
kMaxSetsMultiplierForTesting);
}
static constexpr size_t kTextureStagingBufferSizeForTesting = 128;
......@@ -81,6 +88,7 @@ class VulkanUniformUpdatesTest : public ANGLETest
private:
EGLContext mLastContext;
uint32_t mMaxSetsPerPool;
uint32_t mMaxSetsPerPoolMultiplier;
};
// This test updates a uniform until a new buffer is allocated and then make sure the uniform
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment