Vulkan API要求您使用VkSemaphores同步您的渲染。例如,在渲染一帧时,我们必须等到可以从交换链中获取下一张图像。我们还必须表示可以开始呈现渲染图像。每个Vulkan 教程都会讨论这一点。
信号量在初始化期间创建并在关闭期间销毁。在我能找到的任何示例代码(Sascha Willems,官方 Khronos 示例..)中,VkSemaphore 作为类成员存储在渲染器类中。我想知道是否可以通过创建一个 VulkanSemaphoreManager 类来抽象问题,该类将由渲染器类继承。简而言之,这个类将信号量存储在一个 unordered_map 中,其中 std::string (我给信号量的名称)作为键:
/// @class VulkanSynchronisationManager
/// @brief Creates and destroys Vulkan fences and semaphores.
/// Those are essential for the synchronisation of multithreaded rendering and asynchronous code in general!
/// @note Fences are mainly designed to synchronize your application itself with rendering operation,
/// whereas semaphores are used to synchronize operations within or across command queues.
class VulkanSynchronisationManager
{
private:
// The semaphores that our application needs.
std::unordered_map<std::string, VkSemaphore> semaphores;
public:
VulkanSynchronisationManager()
{}
~VulkanSynchronisationManager()
{}
protected:
/// @brief Checks if a semaphore with this name already exists.
/// @param semaphore_name The name of the semaphore.
/// @return True if a Vulkan semaphore with this name already exists, false otherwise.
bool does_semaphore_exist(const std::string&semaphore_name) const
{
std::unordered_map<std::string, VkSemaphore>::const_iterator semaphore_lookup = semaphores.find(semaphore_name);
if(semaphore_lookup == semaphores.end())
{
return true;
}
return false;
}
/// @brief Creates a new Vulkan semaphore.
/// @param semaphore_name The unique name of the semaphore.
const std::optional<VkSemaphore> VulkanSynchronisationManager::create_semaphore(const VkDevice& vulkan_device, const std::string& semaphore_name) const
{
// First check if a Vulkan semaphore with this name already exists!
if(does_semaphore_exist(semaphore_name))
{
// Error handling...
return std::nullopt;
}
VkSemaphoreCreateInfo semaphore_create_info = {};
// So far, there is nothing to fill into this structure.
// This may change in the future!
// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkSemaphoreCreateInfo.html
semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
semaphore_create_info.pNext = nullptr;
semaphore_create_info.flags = 0;
// The new Vulkan semaphore which will be created.
VkSemaphore new_semaphore;
VkResult result = vkCreateSemaphore(vulkan_device, &semaphore_create_info, nullptr, &new_semaphore);
if(VK_SUCCESS != result)
{
vulkan_error_check(result);
return std::nullopt;
}
// THIS does not work, see following text.
semaphores.insert({semaphore_name, new_semaphore});
return new_semaphore;
}
/// @brief Gets a certain semaphore by name.
/// @param semaphore_name The name of the semaphore.
/// @return The acquired semaphore (if existent), std::nullopt otherwise.
const std::optional<VkSemaphore> get_semaphore(const std::string& semaphore_name) const
{
if(!does_semaphore_exist(semaphore_name))
{
// Error handling...
return std::nullopt;
}
// Return the requested semaphore.
return semaphores.at(semaphore_name);
}
/// @brief Destroys all existing semaphores.
void shutdown_semaphores(const VkDevice& vulkan_device)
{
// Create an iterator for the unordered map.
std::unordered_map<std::string, VkSemaphore>::const_iterator sepahore_iterator = semaphores.begin();
// Iterate over the unordered map.
while(sepahore_iterator != semaphores.end())
{
// Destroy the semaphore.
vkDestroySemaphore(vulkan_device, sepahore_iterator->second, nullptr);
// Move on to the next Semaphore.
sepahore_iterator++;
}
// Clear the unordered map!
semaphores.clear();
}
};
此类捆绑所有现有的信号量并提供创建和获取方法。它还负责在应用程序关闭期间销毁所有信号量。
但是有一个问题:我们不能将新的 VkSemaphore 插入 unordered_map,因为 Vulkan 定义信号量是不可调度的句柄。
毕竟这是个好主意吗?
谢谢你的反馈,约翰。