Vulkan:一次创建一个管道、命令缓冲区等有什么缺点吗?

Vulkan:一次创建一个管道、命令缓冲区等有什么缺点吗?,vulkan,Vulkan,一些Vulkan对象(例如vkPipelines、vkCommandBuffers)可以在数组中创建/分配(使用大小+指针参数)。乍一看,这样做似乎是为了更容易使用常见的使用模式进行编码。但是在某些情况下(例如:当创建一个C++ RAII包装器)时,最好一次创建一个。当然,实现这一点很简单 然而,我想知道这样做是否有任何明显的缺点 (我想这可能会因创建的实际对象类型而异,但我认为对每个对象问相同的问题不是一个好主意) 假设在这两种情况下,对象很可能是以先创建后销毁的方式创建的,并且当对象是单独创

一些Vulkan对象(例如vkPipelines、vkCommandBuffers)可以在数组中创建/分配(使用大小+指针参数)。乍一看,这样做似乎是为了更容易使用常见的使用模式进行编码。但是在某些情况下(例如:当创建一个C++ RAII包装器)时,最好一次创建一个。当然,实现这一点很简单

然而,我想知道这样做是否有任何明显的缺点

(我想这可能会因创建的实际对象类型而异,但我认为对每个对象问相同的问题不是一个好主意)

假设在这两种情况下,对象很可能是以先创建后销毁的方式创建的,并且当对象是单独创建和销毁的时,这可能会在循环中发生

另请注意:

  • vkCommandBuffers也在阵列中释放
  • VG管道单独销毁

我是否有理由修改我的RAII包装器以允许基于数组的创建/销毁?例如,它会(显著)节省内存吗?单一创建会降低性能吗?

Vulkan是一种围绕现代图形硬件设计的API。如果您知道要提前创建一定数量的对象,则应使用批处理函数(如果存在),因为驱动程序可能能够优化创建/分配,从而产生可能更好的性能

可能有(也可能没有)更好的性能(取决于驱动程序和您的工作负载类型)。但显然有潜力获得更好的绩效

如果在应用程序中创建一个或十个命令缓冲区,那么这并不重要

在大多数情况下,这一比例将低于5%。因此,如果您不关心这一点(例如,您的应用程序已经运行了500 FPS),那么这并不重要

再说,C++是一门多用途的语言。我认为这不是问题。您只需要有一个静态成员函数或一个类来构造/初始化N个对象(可能有一个模式名)


破坏可能更为棘手。您可以再次使用静态成员函数来销毁N个对象。但是它不会被自动调用,而且周围有空/外壳对象很烦人。析构函数仍然会在
VK\u NULL\u句柄上调用。还有一个问题,池重置或销毁会使所有命令缓冲区C++对象无效,所以很可能没有办法做到干净/简单。

< P>记住:代码> VKPrime< /Cord>创建不需要外部同步。这意味着进程将处理自己的互斥体等等。因此,尽可能避免锁定这些内部互斥对象是有意义的

而且,这个过程很慢。因此,能够对其进行批处理并将其执行到另一个线程中是非常有用的


命令缓冲区创建没有这两个问题。因此,您应该可以自由分配您需要的任何CBs。但是,多次创建不会损害性能,而且可能会有所帮助。因此没有理由避免它。

我希望(ed)避免它的原因是它使RAII机制复杂化(我现在使用的是自定义RAII对象数组描述符,这是可以接受的)。批量分配还有另一个不太可能的缺点-单一分配可以填补小漏洞。关于VkPipelines:如果您希望避免批量分配,但仍然获得比单一分配更好的性能,您可以使用衍生管道:衍生管道不保证提供任何性能优势。事实上,Nvidia在其“应该做的和不应该做的”列表中有一句话:“不要期望管道衍生产品加速”。