Add an overflow system for descriptor pools that have high use

* This can happen in cases where the application syncs to the GPU after
  using one set of descriptors from a pool, resets it, and then
  allocates more descriptors out of the pool to use later in the frame.
* Since we allocate all descriptors up-front before the frame starts we
  end up allocating more than the high-water mark, and running out of
  room in the pool.
* Instead we just allocate duplicates of the pool as needed, as overflow
  space, and then use those overflow pools to satisfy any extra need.
This commit is contained in:
baldurk
2018-04-05 17:34:13 +01:00
parent 6e5ee75215
commit 6102b638a6
3 changed files with 92 additions and 4 deletions
+34 -1
View File
@@ -631,4 +631,37 @@ void VulkanCreationInfo::ShaderModule::Reflection::Init(VulkanResourceManager *r
refl.rawBytes.assign((byte *)spv.spirv.data(), spv.spirv.size() * sizeof(uint32_t));
}
}
}
}
void VulkanCreationInfo::DescSetPool::Init(VulkanResourceManager *resourceMan,
VulkanCreationInfo &info,
const VkDescriptorPoolCreateInfo *pCreateInfo)
{
maxSets = pCreateInfo->maxSets;
poolSizes.assign(pCreateInfo->pPoolSizes, pCreateInfo->pPoolSizes + pCreateInfo->poolSizeCount);
}
void VulkanCreationInfo::DescSetPool::CreateOverflow(VkDevice device,
VulkanResourceManager *resourceMan)
{
VkDescriptorPoolCreateInfo poolInfo = {
VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
NULL,
0,
maxSets,
(uint32_t)poolSizes.size(),
&poolSizes[0],
};
VkDescriptorPool pool;
VkResult ret = ObjDisp(device)->CreateDescriptorPool(Unwrap(device), &poolInfo, NULL, &pool);
RDCASSERTEQUAL(ret, VK_SUCCESS);
ResourceId poolid = resourceMan->WrapResource(Unwrap(device), pool);
// register as a live-only resource, so it is cleaned up properly
resourceMan->AddLiveResource(poolid, pool);
overflow.push_back(pool);
}
+14
View File
@@ -369,6 +369,20 @@ struct VulkanCreationInfo
};
map<ResourceId, ShaderModule> m_ShaderModule;
struct DescSetPool
{
void Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info,
const VkDescriptorPoolCreateInfo *pCreateInfo);
uint32_t maxSets;
std::vector<VkDescriptorPoolSize> poolSizes;
void CreateOverflow(VkDevice device, VulkanResourceManager *resourceMan);
std::vector<VkDescriptorPool> overflow;
};
map<ResourceId, DescSetPool> m_DescSetPool;
map<ResourceId, string> m_Names;
map<ResourceId, SwapchainInfo> m_SwapChain;
map<ResourceId, DescSetLayout> m_DescSetLayout;
@@ -183,6 +183,8 @@ bool WrappedVulkan::Serialise_vkCreateDescriptorPool(SerialiserType &ser, VkDevi
{
ResourceId live = GetResourceManager()->WrapResource(Unwrap(device), pool);
GetResourceManager()->AddLiveResource(DescriptorPool, pool);
m_CreationInfo.m_DescSetPool[live].Init(GetResourceManager(), m_CreationInfo, &CreateInfo);
}
AddResource(DescriptorPool, ResourceType::Pool, "Descriptor Pool");
@@ -392,10 +394,48 @@ bool WrappedVulkan::Serialise_vkAllocateDescriptorSets(SerialiserType &ser, VkDe
if(ret != VK_SUCCESS)
{
RDCERR("Failed on resource serialise-creation, VkResult: %s", ToStr(ret).c_str());
return false;
RDCWARN(
"Failed to allocate descriptor set %llu from pool %llu on replay. Assuming pool was "
"reset and re-used mid-capture, so overflowing.",
DescriptorSet, GetResourceManager()->GetOriginalID(GetResID(AllocateInfo.descriptorPool)));
VulkanCreationInfo::DescSetPool &poolInfo =
m_CreationInfo.m_DescSetPool[GetResID(AllocateInfo.descriptorPool)];
if(poolInfo.overflow.empty())
{
RDCLOG("Creating first overflow pool");
poolInfo.CreateOverflow(device, GetResourceManager());
}
// first try and use the most recent overflow pool
unwrapped.descriptorPool = Unwrap(poolInfo.overflow.back());
ret = ObjDisp(device)->AllocateDescriptorSets(Unwrap(device), &unwrapped, &descset);
// if we got an error, maybe the latest overflow pool is full. Try to create a new one and use
// that
if(ret != VK_SUCCESS)
{
RDCLOG("Creating new overflow pool, last pool failed with %s", ToStr(ret).c_str());
poolInfo.CreateOverflow(device, GetResourceManager());
unwrapped.descriptorPool = Unwrap(poolInfo.overflow.back());
ret = ObjDisp(device)->AllocateDescriptorSets(Unwrap(device), &unwrapped, &descset);
if(ret != VK_SUCCESS)
{
RDCERR("Failed on resource serialise-creation, even after trying overflow, VkResult: %s",
ToStr(ret).c_str());
return false;
}
}
}
else
// if we got here we must have succeeded
RDCASSERTEQUAL(ret, VK_SUCCESS);
{
ResourceId live = GetResourceManager()->WrapResource(Unwrap(device), descset);
GetResourceManager()->AddLiveResource(DescriptorSet, descset);
@@ -411,6 +451,7 @@ bool WrappedVulkan::Serialise_vkAllocateDescriptorSets(SerialiserType &ser, VkDe
AddResource(DescriptorSet, ResourceType::ShaderBinding, "Descriptor Set");
DerivedResource(device, DescriptorSet);
DerivedResource(AllocateInfo.pSetLayouts[0], DescriptorSet);
DerivedResource(AllocateInfo.descriptorPool, DescriptorSet);
}
return true;