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

时间:2018-06-14 17:18:52

标签: vulkan

我们说我有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分配的内存,这不是我的情况。主机连贯内存是否保证字节粒度内存更新?

2 个答案:

答案 0 :(得分:2)

将缓冲区绑定到内存时,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与所有这些无关。它本质上是缓存行或内存事务大小。对于非连贯的内存,如果你在&#34;非相干原子中写入一个字节&#34;,CPU仍然必须将整个原子写入内存,这意味着你将同时写入任何内容。来自GPU的原子。对于连贯的存储器,CPU和GPU协作使得它们每个都可以写入相邻的字节而不会覆盖彼此的数据。但是,如果您正在使用非连贯内存,并希望在GPU可能正在写入同一VkBuffers中的另一个VkBuffer时写入VkDeviceMemory之一。 },您可能希望确保两个VkBuffers不在缓冲区的同一nonCoherentAtomSize块内重叠。

答案 1 :(得分:1)

如果要创建一个可容纳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并且所需的内存大小和你的缓冲区的大小之间的相对差异可能是小。