-1

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 定义信号量是不可调度的句柄。

毕竟这是个好主意吗?

谢谢你的反馈,约翰。

4

1 回答 1

0

我发现了问题:通过将 create_semaphore 声明为“const”成员函数,我无法修改 unordered_map。

不过感谢您的建议!由于这个类比旧方法大得多,我会重新考虑它。

于 2020-02-16T18:38:10.563 回答