2
3
4
5
9#include "Render/FrameInfo.h"
24 m_CmdBuffers[i].resize(nCmdThreads);
27 m_CmdPools.resize(nCmdThreads);
30
31
54 m_IsPoolRunning =
true;
55 m_InitThreadSize = initThreadSize;
56 m_IdleThreadSize = initThreadSize;
57 m_NThreads = initThreadSize;
59 for (uint32_t i = 0; i < m_InitThreadSize; i++)
61 auto ptr = std::make_unique<Thread<VkCommandBuffer>>(std::bind(&VulkanCmdThreadPool::ThreadFunc,
this, std::placeholders::_1), i);
62 uint32_t threadId = ptr->GetId();
64 m_Threads.emplace(threadId, std::move(ptr));
65 m_Threads[threadId]->Start();
74
75
77 ss << m_PoolName << thread->GetId();
81 auto lastTime = std::chrono::high_resolution_clock::now();
87 std::unique_lock<std::mutex> lock(m_Mutex);
89 while ((m_Tasks.load() == 0 && thread->GetThreadTasksCount() == 0) || m_IsSuspend)
92
93
96 m_Threads.erase(thread->GetId());
98 m_ExitCond.notify_all();
102 if (m_PoolMode == PoolMode::MODE_CACHED)
104 if (m_NotEmpty.wait_for(lock, std::chrono::seconds(1)) == std::cv_status::timeout)
106 auto now = std::chrono::high_resolution_clock::now();
107 auto dur = std::chrono::duration_cast<std::chrono::seconds>(now - lastTime);
110
111
112 if (dur.count() >= m_ThreadIdleTimeOut && m_Threads.size() > m_InitThreadSize)
114 m_Threads.erase(thread->GetId());
123 m_NotEmpty.wait(lock);
128
129
130 task = thread->RequireTask();
133
134
137 task = m_TaskQueue.front();
139 thread->SetThreadInTask(
true);
148 m_NotEmpty.notify_all();
152
153
156 VkCommandBuffer cmdBuffer = CreateParallelCommandBuffers(thread->GetId());
158 thread->SetThreadInTask(
false);
160 m_IdleCond.notify_all();
164 thread->SetThreadInTask(
false);
166 m_IdleCond.notify_all();
169 lastTime = std::chrono::high_resolution_clock::now();
177 if (!m_CmdPools[threadId])
179 m_CmdPools[threadId] = VulkanCommandPool::GetThreadGraphicCommandPool();
182 VkCommandBufferAllocateInfo allocInfo{};
183 allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
184 allocInfo.commandPool = m_CmdPools[threadId];
185 allocInfo.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
186 allocInfo.commandBufferCount = 1;
188 VkCommandBuffer cmdBuffer;
190 VK_CHECK(vkAllocateCommandBuffers(m_VulkanState.m_Device, &allocInfo, &cmdBuffer))
191 DEBUGUTILS_SETOBJECTNAME(VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)cmdBuffer, m_VulkanState.m_Device,
"ParallelGraphicCommandBuffer")
194 m_CmdBuffers[FrameInfo::Get().m_FrameIndex][threadId].push_back(cmdBuffer);
203 auto& commandBuffers = m_CmdBuffers[frameIndex];
205 for (
int i = 0; i < m_NThreads.load(); i++)
207 if (commandBuffers[i].empty())
continue;
209 vkFreeCommandBuffers(m_VulkanState.m_Device, m_CmdPools[i], commandBuffers[i].size(), commandBuffers[i].data());
210 commandBuffers[i].clear();
#define SPICES_PROFILE_ZONE
#define SPICES_PROFILE_VK_COLLECT(cmdbuf)
#define VK_CHECK(expr)
Vulkan Check macro. Verify Vulkan API Effectiveness.
static bool SetThreadName(const std::string &name)
Set Thread name.
Thread Static Function Library.
virtual ~VulkanCmdThreadPool() override
Destructor Function.
void Start(int initThreadSize=0.5 *std::thread::hardware_concurrency())
Start Run this thread pool.
void FreeParallelCommandBuffers(uint32_t frameIndex)
Free all second CommandBuffer in rhi threadPool thread.
void ThreadFunc(Thread< VkCommandBuffer > *thread)
Thread Function.
VkCommandBuffer CreateParallelCommandBuffers(uint32_t threadId)
Create second CommandBuffer in rhi threadPool thread.
VulkanCmdThreadPool(VulkanState &vulkanState, const std::string &name)
Constructor Function. Create Specific ThreadPool.
Wrappers of RHI Thread Pool.
VulkanState & m_VulkanState
The global VulkanState Referenced from VulkanRenderBackend.
VulkanObject(VulkanState &vulkanState)
Constructor Function. Init member variables.
VulkanObject Class. This class defines the basic behaves of VulkanObject. When we create an new Vulka...
PoolMode
ThreadPool Run Mode.
constexpr uint32_t MaxFrameInFlight
Max In Flight Frame. 2 buffers are enough in this program.
This struct contains all Vulkan object in used global.