VkMemoryRequirements
结构获取正确的值,而不必先分配缓冲区也无需使用vkGetBufferMemoryRequirements
? 我有一个执行以下操作的应用程序,并且一切正常。
VkMemoryRequirements memReq;
vkGetBufferMemoryRequirements(application.shell->device, uniformBuffer, &memReq);
int memType = application.shell->findMemoryType(memReq.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
在内部,findMemoryType
遍历内存类型并检查它们是否具有必需的属性标志。
如果我将对vkGetMemoryRequirements
的调用替换为硬编码的值(这些值不是可移植的,特定于我的系统,并且是通过调试获得的),那么一切仍然有效,并且不会收到任何验证错误。
VkMemoryRequirements memReq = { 768, 256, 1665 };
int memType = application.shell->findMemoryType(memReq.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
上面的代码是恕我直言的,因为它可以在您真正需要它之前预先分配内存。
在Vulkan中,您创建最初不由设备内存支持的缓冲区,并在稍后阶段使用vkBindBufferMemory
分配内存并将其绑定到缓冲区:
VkResult vkBindBufferMemory(
VkDevice device,
VkBuffer buffer,
VkDeviceMemory memory,
VkDeviceSize memoryOffset);
其Vulkan规范指出:
必须使用允许的一种内存类型分配内存 在VkMemoryRequirements结构的memoryTypeBits成员中 调用带有缓冲区的vkGetBufferMemoryRequirements返回的
这暗示着在为缓冲区分配内存之前,您应该已经创建了缓冲区。
我觉得在某些情况下,在实际需要之前预先分配一块内存会很有用;在大多数OpenGL风格中,我都无法做到这一点,但是Vulkan不应受此限制的影响,对吗?
很显然,当您为第一个缓冲区分配内存时,您可以分配更多的内存,以便当您需要第二个缓冲区时,可以将其绑定到同一块中的另一个范围。但是我的理解是,为了符合规范,您仍然需要在第二个缓冲区上调用vkGetBufferMemoryRequirements
,即使它的类型和大小与第一个相同。
答案 0 :(得分:2)
该问题已经认识到答案为“否”;您似乎只是想对已经知道的内容做一个最终的尝试。你不能做到的。
您使用硬编码值显示的代码有效,因为您已经知道答案。不是Vulkan要求您提出问题; Vulkan要求您提供使用答案的缓冲区。
但是,由于“答案”是特定于实现的,因此它会根据硬件而变化。安装新的驱动程序时,它可能会更改。实际上,即使您在创建VkDevice
时激活了哪些扩展或Vulkan功能,它也可能会改变。
话虽如此:
这暗示着在为缓冲区分配内存之前,您应该已经创建了缓冲区。
不正确。它要求您有答案,并且已选择适合该答案的内存和字节偏移。但是Vulkan对于“答案”的实际含义是松散的。
Vulkan具有specific guarantees in place,可让您知道特定缓冲区/图像的答案,而不必询问那个 specific VkBuffer/Image
对象。细节有些复杂,但是对于缓冲区来说,它们却很松懈。
基本思想是,您可以创建测试VkBuffer/Image
并询问其内存属性。然后,您可以使用该答案来了解您打算使用的与该缓冲区“相似”的属性。至少,Vulkan保证两个相同的缓冲区/图像(格式,使用标志,大小等)将始终产生相同的内存属性。
但是Vulkan还提供其他一些保证。内存属性基本上告诉您3件事:
对于大小,您只能获得最基本的保证:等效的缓冲区/图像将产生等效的大小。
对于对齐,图像与尺寸一样严格:仅保证等效的图像产生等效的对齐。但是对于缓冲区来说,事情就更加松懈了。如果测试缓冲区仅在使用情况标志方面有所不同,并且最终缓冲区使用了使用情况标志的子集,则最终缓冲区的对齐方式不会比测试缓冲区更具限制性。因此,您可以使用测试缓冲区中的对齐方式。
对于内存类型,情况更加松散。对于图像,唯一重要的是:
如果两个VkImage
对象的所有这些都相同,则该标准保证所有此类图像将支持同一组内存类型。
对于缓冲区而言,事情更加松懈。对于非稀疏缓冲区,如果您的测试缓冲区与最终缓冲区仅在使用情况标志方面有所不同,则如果最后一个缓冲区具有测试缓冲区的使用情况标志的子集,则它所支持的内存类型集必须包括所有来自测试缓冲区的内容。最终缓冲区可以支持更多,但必须至少支持此类测试缓冲区。
噢,线性图像和缓冲区必须始终能够至少在一种可映射的,相干的存储器类型中使用。当然,这要求您使用这些用法和标志字段创建了一个有效的VkDevice/Image
,因此,如果设备不允许(例如)将线性图像用作纹理,则在询问之前将其停下来关于内存属性。