已关闭
[ArkWeb][安全][上游社区漏洞修复][BUG-536636648] 描述符池回收修复 #470
。创建于 8 天前关闭于 8 天前
[ArkWeb][安全][上游社区漏洞修复][BUG-536636648] 描述符池回收修复 #470
已关闭
共 3 个文件变更+52-2
| @@ -3505,6 +3505,15 @@ void DescriptorPoolHelper::cleanupPendingGarbage() | |||
| 3505 | } | 3505 | } |
| 3506 | } | 3506 | } |
| 3507 | 3507 | ||
| 3508 | +void DescriptorPoolHelper::forceFinishPendingGarbage() | ||
| 3509 | +{ | ||
| 3510 | + while (!mPendingGarbageList.empty()) | ||
| 3511 | + { | ||
| 3512 | + mFinishedGarbageList.push_back(std::move(mPendingGarbageList.front())); | ||
| 3513 | + mPendingGarbageList.pop_front(); | ||
| 3514 | + } | ||
| 3515 | +} | ||
| 3516 | + | ||
| 3508 | bool DescriptorPoolHelper::recycleFromGarbage(Renderer *renderer, | 3517 | bool DescriptorPoolHelper::recycleFromGarbage(Renderer *renderer, |
| 3509 | DescriptorSetPointer *descriptorSetOut) | 3518 | DescriptorSetPointer *descriptorSetOut) |
| 3510 | { | 3519 | { |
| @@ -3627,7 +3636,11 @@ void DynamicDescriptorPool::destroy(VkDevice device) | |||
| 3627 | 3636 | ||
| 3628 | for (DescriptorPoolPointer &pool : mDescriptorPools) | 3637 | for (DescriptorPoolPointer &pool : mDescriptorPools) |
| 3629 | { | 3638 | { |
| 3630 | - pool->cleanupPendingGarbage(); | 3639 | + // Usually all pending garbage should have been finished when DynamicDescriptorPool is |
| 3640 | + // destroyed. But when context runs into error and submit code path early out, we could have | ||
| 3641 | + // unfinished garbage in the pending list. So force all pending garbage to be cleared rather | ||
| 3642 | + // than being left in place until the pool itself is deleted. | ||
| 3643 | + pool->forceFinishPendingGarbage(); | ||
| 3631 | pool->destroyGarbage(); | 3644 | pool->destroyGarbage(); |
| 3632 | ASSERT(pool.unique()); | 3645 | ASSERT(pool.unique()); |
| 3633 | } | 3646 | } |
| @@ -298,6 +298,7 @@ class DescriptorPoolHelper final : angle::NonCopyable | |||
| 298 | bool recycleFromGarbage(Renderer *renderer, DescriptorSetPointer *descriptorSetOut); | 298 | bool recycleFromGarbage(Renderer *renderer, DescriptorSetPointer *descriptorSetOut); |
| 299 | void destroyGarbage(); | 299 | void destroyGarbage(); |
| 300 | void cleanupPendingGarbage(); | 300 | void cleanupPendingGarbage(); |
| 301 | + void forceFinishPendingGarbage(); | ||
| 301 | 302 | ||
| 302 | bool hasValidDescriptorSet() const { return mValidDescriptorSets != 0; } | 303 | bool hasValidDescriptorSet() const { return mValidDescriptorSets != 0; } |
| 303 | bool canDestroy() const { return mValidDescriptorSets == 0 && mPendingGarbageList.empty(); } | 304 | bool canDestroy() const { return mValidDescriptorSets == 0 && mPendingGarbageList.empty(); } |
| @@ -208,7 +208,43 @@ TEST_P(VulkanDescriptorSetLayoutDescTest, Basic) | |||
| 208 | mDescriptorSetLayoutCache.destroy(contextVk->getRenderer()); | 208 | mDescriptorSetLayoutCache.destroy(contextVk->getRenderer()); |
| 209 | } | 209 | } |
| 210 | 210 | ||
| 211 | +// Verify that DynamicDescriptorPool::destroy tears down cleanly even when descriptor sets that | ||
| 212 | +// were returned to the pool are still tagged with an outstanding queue serial. | ||
| 213 | +TEST_P(VulkanDescriptorSetLayoutDescTest, DestroyWithPendingGarbage) | ||
| 214 | +{ | ||
| 215 | + rx::ContextVk *contextVk = hackANGLE(); | ||
| 216 | + | ||
| 217 | + rx::vk::DescriptorSetLayoutDesc desc; | ||
| 218 | + addBindings({0}, &desc); | ||
| 219 | + | ||
| 220 | + rx::vk::DescriptorSetLayoutPtr descriptorSetLayout; | ||
| 221 | + angle::Result result = | ||
| 222 | + mDescriptorSetLayoutCache.getDescriptorSetLayout(contextVk, desc, &descriptorSetLayout); | ||
| 223 | + ASSERT_EQ(result, angle::Result::Continue); | ||
| 224 | + | ||
| 225 | + VkDescriptorPoolSize poolSize = {VK_DESCRIPTOR_TYPE_SAMPLER, 1}; | ||
| 226 | + rx::vk::DynamicDescriptorPool dynamicPool; | ||
| 227 | + result = dynamicPool.init(contextVk, &poolSize, 1, *descriptorSetLayout); | ||
| 228 | + ASSERT_EQ(result, angle::Result::Continue); | ||
| 229 | + | ||
| 230 | + rx::vk::DescriptorSetPointer descriptorSet; | ||
| 231 | + result = dynamicPool.allocateDescriptorSet(contextVk, *descriptorSetLayout, &descriptorSet); | ||
| 232 | + ASSERT_EQ(result, angle::Result::Continue); | ||
| 233 | + ASSERT_TRUE(descriptorSet); | ||
| 234 | + | ||
| 235 | + // Tag the descriptor set with a queue serial that has not been reached so that it stays on the | ||
| 236 | + // pool's pending garbage list once released. | ||
| 237 | + descriptorSet->setQueueSerial(rx::QueueSerial(0, rx::Serial::Infinite())); | ||
| 238 | + descriptorSet.reset(); | ||
| 239 | + | ||
| 240 | + dynamicPool.destroy(contextVk->getDevice()); | ||
| 241 | + | ||
| 242 | + descriptorSetLayout.reset(); | ||
| 243 | + mDescriptorSetLayoutCache.destroy(contextVk->getRenderer()); | ||
| 244 | +} | ||
| 245 | + | ||
| 211 | ANGLE_INSTANTIATE_TEST(VulkanDescriptorSetTest, ES31_VULKAN(), ES31_VULKAN_SWIFTSHADER()); | 246 | ANGLE_INSTANTIATE_TEST(VulkanDescriptorSetTest, ES31_VULKAN(), ES31_VULKAN_SWIFTSHADER()); |
| 212 | -ANGLE_INSTANTIATE_TEST(VulkanDescriptorSetLayoutDescTest, ES31_VULKAN()); | 247 | +ANGLE_INSTANTIATE_TEST(VulkanDescriptorSetLayoutDescTest, ES31_VULKAN(), ES31_VULKAN_SWIFTSHADER()); |
| 248 | +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VulkanDescriptorSetLayoutDescTest); | ||
| 213 | 249 | ||
| 214 | } // namespace | 250 | } // namespace |