Hash :
9b6368cc
Author :
Date :
2023-03-14T14:48:30
Vulkan: Fix freeing Secondary Command Buffers from wrong thread. Problem: - Secondary Command Buffers are freed in the "CommandQueue" class. - This may happen from any Context thread that calls "checkCompletedCommands()" or "finish<*>()" methods. - As the result, one Command Buffer may be freed from one thread, while other Command Buffer from the same "VkCommandPool" is allocated/reset/recorded in the other thread. Vulkan spec demands external "VkCommandPool" synchronization for any modifications (begin/end/reset/free/cmd) on its "VkCommandBuffer"s. Fix: - Added new "rx::vk::SecondaryCommandPool" class that replaces the "rx::vk::CommandPool" wrapper. - This class has "collect()" method for storing "VkCommandBuffer"s. Collected buffers are freed from the correct thread on the next "allocate()" call. This CL only fixes the problem, keeping Secondary Command Buffer memory management as is (allocate/free single buffer without reuse). In the future CLs this behavior may be changed (reuse buffers, reset/free entire pools). Bug: angleproject:6100 Change-Id: If938416c4df4fe55f0cfb418b6759721ac53098b Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4334577 Reviewed-by: Charlie Lao <cclao@google.com> Commit-Queue: Igor Nazarov <i.nazarov@samsung.com> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
//
// Copyright 2023 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// SecondaryCommandPool:
// A class for allocating Command Buffers for VulkanSecondaryCommandBuffer.
//
#ifndef LIBANGLE_RENDERER_VULKAN_SECONDARYCOMMANDPOOL_H_
#define LIBANGLE_RENDERER_VULKAN_SECONDARYCOMMANDPOOL_H_
#include "common/FixedQueue.h"
#include "libANGLE/renderer/vulkan/vk_command_buffer_utils.h"
#include "libANGLE/renderer/vulkan/vk_wrapper.h"
namespace rx
{
namespace vk
{
class Context;
class VulkanSecondaryCommandBuffer;
// VkCommandPool must be externally synchronized when its Command Buffers are: allocated, freed,
// reset, or recorded. This class ensures that Command Buffers are freed from the thread that
// recording commands (Context thread).
class SecondaryCommandPool final : angle::NonCopyable
{
public:
SecondaryCommandPool();
~SecondaryCommandPool();
angle::Result init(Context *context, uint32_t queueFamilyIndex, ProtectionType protectionType);
void destroy(VkDevice device);
bool valid() const { return mCommandPool.valid(); }
// Call only from the Context thread that owns the SecondaryCommandPool instance.
angle::Result allocate(Context *context, VulkanSecondaryCommandBuffer *buffer);
// Single threaded - use external synchronization.
// Example threads: any Context thread or "asyncCommandQueue" thread.
void collect(VulkanSecondaryCommandBuffer *buffer);
private:
static constexpr size_t kFixedQueueLimit = 100u;
// Context thread access members.
void freeCollectedBuffers(VkDevice device);
// Use single pool for now.
CommandPool mCommandPool;
// Other thread access members.
// Fast lock free queue for processing buffers while new may be added from the other thread.
angle::FixedQueue<VkCommandBuffer, kFixedQueueLimit> mCollectedBuffers;
// Overflow vector to use in cases when FixedQueue is filled.
std::vector<VkCommandBuffer> mCollectedBuffersOverflow;
std::mutex mOverflowMutex;
std::atomic<bool> mHasOverflow;
};
} // namespace vk
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_SECONDARYCOMMANDPOOL_H_