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) ...@@ -562,7 +562,8 @@ bool IsShaderReadOnlyLayout(const ImageMemoryBarrierData &imageLayout)
} // anonymous namespace } // anonymous namespace
// This is an arbitrary max. We can change this later if necessary. // 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) VkImageLayout ConvertImageLayoutToVkImageLayout(ImageLayout imageLayout)
{ {
...@@ -1674,7 +1675,7 @@ bool DescriptorPoolHelper::hasCapacity(uint32_t descriptorSetCount) const ...@@ -1674,7 +1675,7 @@ bool DescriptorPoolHelper::hasCapacity(uint32_t descriptorSetCount) const
} }
angle::Result DescriptorPoolHelper::init(ContextVk *contextVk, angle::Result DescriptorPoolHelper::init(ContextVk *contextVk,
const std::vector<VkDescriptorPoolSize> &poolSizes, const std::vector<VkDescriptorPoolSize> &poolSizesIn,
uint32_t maxSets) uint32_t maxSets)
{ {
if (mDescriptorPool.valid()) if (mDescriptorPool.valid())
...@@ -1683,6 +1684,14 @@ angle::Result DescriptorPoolHelper::init(ContextVk *contextVk, ...@@ -1683,6 +1684,14 @@ angle::Result DescriptorPoolHelper::init(ContextVk *contextVk,
mDescriptorPool.destroy(contextVk->getDevice()); 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 = {}; VkDescriptorPoolCreateInfo descriptorPoolInfo = {};
descriptorPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; descriptorPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
descriptorPoolInfo.flags = 0; descriptorPoolInfo.flags = 0;
...@@ -1748,11 +1757,6 @@ angle::Result DynamicDescriptorPool::init(ContextVk *contextVk, ...@@ -1748,11 +1757,6 @@ angle::Result DynamicDescriptorPool::init(ContextVk *contextVk,
ASSERT(mCachedDescriptorSetLayout == VK_NULL_HANDLE); ASSERT(mCachedDescriptorSetLayout == VK_NULL_HANDLE);
mPoolSizes.assign(setSizes, setSizes + setSizeCount); mPoolSizes.assign(setSizes, setSizes + setSizeCount);
for (uint32_t i = 0; i < setSizeCount; ++i)
{
mPoolSizes[i].descriptorCount *= mMaxSetsPerPool;
}
mCachedDescriptorSetLayout = descriptorSetLayout; mCachedDescriptorSetLayout = descriptorSetLayout;
mDescriptorPools.push_back(new RefCountedDescriptorPoolHelper()); mDescriptorPools.push_back(new RefCountedDescriptorPoolHelper());
...@@ -1847,19 +1851,40 @@ angle::Result DynamicDescriptorPool::allocateNewPool(ContextVk *contextVk) ...@@ -1847,19 +1851,40 @@ angle::Result DynamicDescriptorPool::allocateNewPool(ContextVk *contextVk)
ANGLE_VK_CHECK(contextVk, mDescriptorPools.size() < kMaxPools, VK_ERROR_TOO_MANY_OBJECTS); 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); return mDescriptorPools[mCurrentPoolIndex]->get().init(contextVk, mPoolSizes, mMaxSetsPerPool);
} }
// For testing only!
uint32_t DynamicDescriptorPool::GetMaxSetsPerPoolForTesting() uint32_t DynamicDescriptorPool::GetMaxSetsPerPoolForTesting()
{ {
return mMaxSetsPerPool; return mMaxSetsPerPool;
} }
// For testing only!
void DynamicDescriptorPool::SetMaxSetsPerPoolForTesting(uint32_t maxSetsPerPool) void DynamicDescriptorPool::SetMaxSetsPerPoolForTesting(uint32_t maxSetsPerPool)
{ {
mMaxSetsPerPool = 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 // DynamicallyGrowingPool implementation
template <typename Pool> template <typename Pool>
DynamicallyGrowingPool<Pool>::DynamicallyGrowingPool() DynamicallyGrowingPool<Pool>::DynamicallyGrowingPool()
......
...@@ -253,7 +253,7 @@ class DescriptorPoolHelper ...@@ -253,7 +253,7 @@ class DescriptorPoolHelper
bool hasCapacity(uint32_t descriptorSetCount) const; bool hasCapacity(uint32_t descriptorSetCount) const;
angle::Result init(ContextVk *contextVk, angle::Result init(ContextVk *contextVk,
const std::vector<VkDescriptorPoolSize> &poolSizes, const std::vector<VkDescriptorPoolSize> &poolSizesIn,
uint32_t maxSets); uint32_t maxSets);
void destroy(VkDevice device); void destroy(VkDevice device);
void release(ContextVk *contextVk); void release(ContextVk *contextVk);
...@@ -317,11 +317,15 @@ class DynamicDescriptorPool final : angle::NonCopyable ...@@ -317,11 +317,15 @@ class DynamicDescriptorPool final : angle::NonCopyable
// For testing only! // For testing only!
static uint32_t GetMaxSetsPerPoolForTesting(); static uint32_t GetMaxSetsPerPoolForTesting();
static void SetMaxSetsPerPoolForTesting(uint32_t maxSetsPerPool); static void SetMaxSetsPerPoolForTesting(uint32_t maxSetsPerPool);
static uint32_t GetMaxSetsPerPoolMultiplierForTesting();
static void SetMaxSetsPerPoolMultiplierForTesting(uint32_t maxSetsPerPool);
private: private:
angle::Result allocateNewPool(ContextVk *contextVk); angle::Result allocateNewPool(ContextVk *contextVk);
static constexpr uint32_t KMaxSetsPerPoolMax = 512;
static uint32_t mMaxSetsPerPool; static uint32_t mMaxSetsPerPool;
static uint32_t mMaxSetsPerPoolMultiplier;
size_t mCurrentPoolIndex; size_t mCurrentPoolIndex;
std::vector<RefCountedDescriptorPoolHelper *> mDescriptorPools; std::vector<RefCountedDescriptorPoolHelper *> mDescriptorPools;
std::vector<VkDescriptorPoolSize> mPoolSizes; std::vector<VkDescriptorPoolSize> mPoolSizes;
......
...@@ -29,22 +29,30 @@ class VulkanDescriptorSetTest : public ANGLETest ...@@ -29,22 +29,30 @@ class VulkanDescriptorSetTest : public ANGLETest
void testSetUp() override void testSetUp() override
{ {
mMaxSetsPerPool = rx::vk::DynamicDescriptorPool::GetMaxSetsPerPoolForTesting(); mMaxSetsPerPool = rx::vk::DynamicDescriptorPool::GetMaxSetsPerPoolForTesting();
mMaxSetsPerPoolMultiplier =
rx::vk::DynamicDescriptorPool::GetMaxSetsPerPoolMultiplierForTesting();
} }
void testTearDown() override void testTearDown() override
{ {
rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolForTesting(mMaxSetsPerPool); 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() void limitMaxSets()
{ {
rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolForTesting(kMaxSetsForTesting); rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolForTesting(kMaxSetsForTesting);
rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolMultiplierForTesting(
kMaxSetsMultiplierForTesting);
} }
private: private:
uint32_t mMaxSetsPerPool; uint32_t mMaxSetsPerPool;
uint32_t mMaxSetsPerPoolMultiplier;
}; };
// Test atomic counter read. // Test atomic counter read.
......
...@@ -41,11 +41,15 @@ class VulkanUniformUpdatesTest : public ANGLETest ...@@ -41,11 +41,15 @@ class VulkanUniformUpdatesTest : public ANGLETest
mLastContext = getEGLWindow()->getContext(); mLastContext = getEGLWindow()->getContext();
mMaxSetsPerPool = rx::vk::DynamicDescriptorPool::GetMaxSetsPerPoolForTesting(); mMaxSetsPerPool = rx::vk::DynamicDescriptorPool::GetMaxSetsPerPoolForTesting();
mMaxSetsPerPoolMultiplier =
rx::vk::DynamicDescriptorPool::GetMaxSetsPerPoolMultiplierForTesting();
} }
void testTearDown() override void testTearDown() override
{ {
rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolForTesting(mMaxSetsPerPool); rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolForTesting(mMaxSetsPerPool);
rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolMultiplierForTesting(
mMaxSetsPerPoolMultiplier);
} }
rx::ContextVk *hackANGLE() const rx::ContextVk *hackANGLE() const
...@@ -63,11 +67,14 @@ class VulkanUniformUpdatesTest : public ANGLETest ...@@ -63,11 +67,14 @@ class VulkanUniformUpdatesTest : public ANGLETest
return rx::vk::GetImpl(texture); 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() void limitMaxSets()
{ {
rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolForTesting(kMaxSetsForTesting); rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolForTesting(kMaxSetsForTesting);
rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolMultiplierForTesting(
kMaxSetsMultiplierForTesting);
} }
static constexpr size_t kTextureStagingBufferSizeForTesting = 128; static constexpr size_t kTextureStagingBufferSizeForTesting = 128;
...@@ -81,6 +88,7 @@ class VulkanUniformUpdatesTest : public ANGLETest ...@@ -81,6 +88,7 @@ class VulkanUniformUpdatesTest : public ANGLETest
private: private:
EGLContext mLastContext; EGLContext mLastContext;
uint32_t mMaxSetsPerPool; uint32_t mMaxSetsPerPool;
uint32_t mMaxSetsPerPoolMultiplier;
}; };
// This test updates a uniform until a new buffer is allocated and then make sure the uniform // 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