gpt4 book ai didi

凡尔康 API : moving rending work into its own thread

转载 作者:行者123 更新时间:2023-12-05 04:07:34 28 4
gpt4 key购买 nike

我正在学习 Khronos Vulkan API,但我很难跨多个线程进行同步。

我试图将渲染工作分解到它自己的线程中。我的想法是有一个主线程,它将负责高级应用程序管理,重要的是,它将调用 VkQueuePresentKHR() 来呈现表面。然而,实际的 VkCmd* 渲染工作是在专用线程上完成的。

我希望我的应用使用三重缓冲,因为流畅的 60fps 对我来说非常重要。在视频演示中,NVIDIA 提到您需要每个帧缓冲区有 1 个 VkCommandPool,并且在每次使用后清除整个池;这比尝试清理单个命令缓冲区更有效。我要更进一步:我正在尝试将渲染工作分解为 6 ​​个队列:

  • 3 个图形队列:每个帧都有自己的专用队列。
  • 1 份用于演示。
  • 1 个杂项一次性图形命令。
  • 1 份用于专门的转移工作

我的 GTX770 显卡有 16 个通用队列 + 1 个专用传输队列,所以这应该没问题。每个队列都有自己的 VkCommandPool。 Queues、CommandPool 和 CommandBuffer 对象在主线程中创建,然后在 Render 线程中使用。

enter image description here

我遇到了以下问题:

  • VkAcquireNextImageKHR 在渲染线程中被调用。如果线程获取 3 张图像,那么我不能再次调用该函数并依赖它阻塞直到下一张图像可用。相反,我得到了一个验证层错误,表明我已经获取了所有可用的图像。而且,无论如何,我更愿意检测到当前没有图像可用,这样我就可以在线程中做其他工作,比如整理内存碎片。我如何判断当前已获取所有图像,以及我不应该调用 vkAcquireNextImageKHR。
  • 如何确定 vkQueuePresentKHR() 是否已完成呈现,以及我是否可以发送另一个要呈现的帧?我不知道如何判断何时可以再次开始使用该帧缓冲区。
  • 在 vkQueueSubmit() 返回后立即清除 CommandPool 是不安全的,对吗?要清除 CommandPool,我是否需要监视提供给 vkQueueSubmit() 的围栏?阅读规范后,我并不完全清楚。
  • 我知道从多个线程中处理一个 CommandPool 是不安全的,但是从一个线程中处理多个队列/CommandPool 可以吗?
  • 我可能做错了什么,但看起来在某些栅栏上调用 vkResetFence() 之后,你不能再调用 vkGetFenceStatus() 了,否则你会得到一个验证层错误。这个对吗?

最佳答案

  1. vkAcquireNextImageKHR 获取图像的所有权,vkQueuePresentKHR 将其所有权释放回呈现引擎。 PE 需要拥有它当前显示的图像,有时还需要拥有其他图像。获取将阻塞,直到图像可用或超时到期。当您无法依靠 Acquire 返回时,您会收到验证错误,因为您没有提供足够的图像。规范说:

    Let n be the total number of images in the swapchain, m be the value of VkSurfaceCapabilitiesKHR::minImageCount, and a be the number of presentable images that the application has currently acquired (i.e. images acquired with vkAcquireNextImageKHR, but not yet presented with vkQueuePresentKHR). vkAcquireNextImageKHR can always succeed if an - m at the time vkAcquireNextImageKHR is called. vkAcquireNextImageKHR should not be called if a > n - m with a timeout of UINT64_MAX; in such a case, vkAcquireNextImageKHR may block indefinitely.

  2. 您传递给 vkAcquireNextImageKHR 的信号量/栅栏将在 PE 完成从图像读取时发出信号。届时,您可以再次开始写入,并在准备好时展示它。

  3. 只要其中的任何命令缓冲区仍在执行,您就无法清除命令池。当栅栏传递给 vkQueueSubmit 信号时,您知道它们何时完成执行。

  4. 是的,您可以在单个线程中使用任意数量的任意类型的对象。 Vulkan 实现中的任何内容都不会绑定(bind)到它所使用的特定线程。从多个线程并发访问对象的限制类似于您对自己的对象的限制:某些对象在内部序列化,因此可以并发访问,但其他对象则不行。

  5. 这似乎是错误的。您应该能够随时在任何有效的围栏上调用 vkGetFenceStatus

关于凡尔康 API : moving rending work into its own thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48614910/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com