mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-04 09:00:44 +00:00
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:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user