一个主机可见缓冲区而不是多个 - 我应该考虑一些对齐吗?



假设我有280字节的数据。如果我创建一个缓冲区,那么根据VkMemoryRequirements分配的大小应该是512字节,对齐512- 这很清楚。但是我需要一个主机可见的大缓冲区,它可以容纳 3 个这样的数据(根据 nvidia 的说法,这比 3 个缓冲区要好(。而且我不清楚 - 我应该指定VkBufferCreateInfo::size等于280 * 3还是512 * 3?如果我把它等于512 * 3那是浪费空间。如果我将其等于280 * 3则在映射内存时会遇到问题吗?规范提到映射范围应该是VkPhysicalDeviceLimits::nonCoherentAtomSize的倍数,但仅适用于在没有VK_MEMORY_PROPERTY_HOST_COHERENT_BIT的情况下分配的内存,这不是我的情况。主机相干内存是否保证字节粒度内存更新?

如果要创建一个可以容纳3 * 280字节数据的缓冲区,则需要创建一个可以容纳3 * 280字节数据的缓冲区(您需要在缓冲区创建期间将此值指定为大小(。但是它需要多少内存(内存对象应该有多大(,这取决于驱动程序。您需要创建一个大小等于3 * 280的缓冲区,然后您需要检查它的内存要求,然后分配必要的内存对象(或从较大的内存对象子分配(并将此内存绑定到缓冲区。

至于对齐 - 如果要将单个内存对象的一部分绑定到多个资源(缓冲区或图像(,这很重要。在您的示例中,您可以创建 3 个缓冲区,可以容纳 280 字节的数据。但是(如vkGetBufferMemoryRequirements()函数所示(每个这样的缓冲区需要 512 字节的内存与 512 字节对齐。因此,对于 3 个单独的缓冲区,您将需要 3 个单独的内存对象,每个大小为 512 字节,或者一个大小为 1536 字节的内存对象。然后,从偏移量 0 到第一个缓冲区的内存范围可以绑定到第一个缓冲区,从偏移量 512 绑定到第二个缓冲区,从偏移量 1024 绑定到第三个缓冲区。但是,尽管您将 512 字节的内存绑定到缓冲区,但不要忘记缓冲区仍然只能容纳 280 字节的内存。

在此示例中,大小和对齐方式相同(均为 512(。假设大小为 380 字节的缓冲区需要内存中的 386 字节与 512 对齐。这种情况不会改变任何东西 - 您的第一个缓冲区绑定到偏移量 0(此偏移量始终满足所有对齐要求(,第二个缓冲区绑定到偏移量 512,第三个缓冲区绑定到偏移量 1024。通常,对齐意味着绑定到资源的内存范围的开始必须是给定对齐值的倍数(从内存对象的开头开始计数(。

在您的情况下,一个大的缓冲区可能更好(就浪费的内存空间而言(:3 * 280等于840,所需内存大小与缓冲区大小之间的相对差异可能会更小。

将缓冲区绑定到内存时,memoryOffset必须是VkMemoryRequirements中返回的对齐值的倍数。因此,您应该有三个VkBuffers,每个 280 字节,但您需要将它们绑定为:

// stride = 512 in your example: 512 rounded up to a multiple of 512.
// would still be true if memoryRequirements.size was just 280.
// if 512 < memoryRequirements.size <= 1024, stride would be 1024, etc.
VkDeviceSize stride = round_up(memoryRequirement.size, memoryRequirement.alignment);
vkBindBufferMemory(device, buffer0, memory, 0 * stride);
vkBindBufferMemory(device, buffer1, memory, 1 * stride);
vkBindBufferMemory(device, buffer2, memory, 2 * stride);

因此,在您的示例中,VkDeviceMemory的大小需要为3*memoryRequirements.size或 1536 字节。

nonCoherentAtomSize独立于所有这些。它本质上是缓存行或内存事务大小。对于非相干内存,如果您在"非相干原子"中写入一个字节,CPU 仍然必须将整个原子写出到内存中,这意味着您将阻止从 GPU 对该原子的任何同时写入。通过相干内存,CPU 和 GPU 协作,以便它们可以各自写入相邻字节而不会覆盖彼此的数据。但是,如果您使用的是非相干内存,并且想要写入其中一台VkBuffers,而 GPU 可能正在写入同一VkDeviceMemory中的另一个VkBuffer,您可能希望确保这两个VkBuffers不会在缓冲区的同一nonCoherentAtomSize块中重叠。

相关内容

最新更新