diff --git a/renderdoc/driver/vulkan/vk_info.cpp b/renderdoc/driver/vulkan/vk_info.cpp index 47d655568..c6a6d4d88 100644 --- a/renderdoc/driver/vulkan/vk_info.cpp +++ b/renderdoc/driver/vulkan/vk_info.cpp @@ -631,4 +631,37 @@ void VulkanCreationInfo::ShaderModule::Reflection::Init(VulkanResourceManager *r refl.rawBytes.assign((byte *)spv.spirv.data(), spv.spirv.size() * sizeof(uint32_t)); } } -} \ No newline at end of file +} + +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); +} diff --git a/renderdoc/driver/vulkan/vk_info.h b/renderdoc/driver/vulkan/vk_info.h index 6f2f38e55..31ebb7aa7 100644 --- a/renderdoc/driver/vulkan/vk_info.h +++ b/renderdoc/driver/vulkan/vk_info.h @@ -369,6 +369,20 @@ struct VulkanCreationInfo }; map m_ShaderModule; + struct DescSetPool + { + void Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info, + const VkDescriptorPoolCreateInfo *pCreateInfo); + + uint32_t maxSets; + std::vector poolSizes; + + void CreateOverflow(VkDevice device, VulkanResourceManager *resourceMan); + + std::vector overflow; + }; + map m_DescSetPool; + map m_Names; map m_SwapChain; map m_DescSetLayout; diff --git a/renderdoc/driver/vulkan/wrappers/vk_descriptor_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_descriptor_funcs.cpp index 288e7bbad..aae002be1 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_descriptor_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_descriptor_funcs.cpp @@ -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;