派生`VkMemoryRequirements`
Deriving the `VkMemoryRequirements`
- 有没有一种方法可以为
VkMemoryRequirements
结构获取正确的值,而无需先分配缓冲区且无需使用 vkGetBufferMemoryRequirements
?
- 是supported/compliant吗
动机 - 简短版
我有一个应用程序执行以下操作,并且一切正常。
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 规范指出:
memory must have been allocated using one of the memory types allowed
in the memoryTypeBits member of the VkMemoryRequirements structure
returned from a call to vkGetBufferMemoryRequirements with buffer
这意味着在为缓冲区分配内存之前,您应该已经创建了缓冲区。
我感觉在某些情况下,在您实际需要之前预分配一块内存会很有用;在我体验过的大多数 OpenGL 风格中,这是不可能的,但是 Vulkan 不应该受到这个限制,对吧?
- 在创建第一个缓冲区之前是否有一种(或多或少是自动的)方法来获取内存需求?
- 是supported/compliant吗?
显然,当您 do 为第一个缓冲区分配内存时,您可以分配更多的内存,这样当您需要第二个缓冲区时,您可以将它绑定到相同的块。但我的理解是,为了符合规范,您仍然需要在第二个缓冲区上调用 vkGetBufferMemoryRequirements
,即使它与第一个缓冲区的类型和大小完全相同。
本题已经识别答案为"no";你似乎只是想围绕你已经知道的事情做一个结束-运行。你不能。
您使用硬编码值显示的代码有效,因为您已经知道答案。并不是 Vulkan 要求您提出问题;而是Vulkan 要求您提供使用答案的缓冲区。
但是,由于 "the answer" 是特定于实现的,因此它会根据硬件而变化。当您安装新的驱动程序时,它可能会发生变化。事实上,它甚至可以根据您在创建 VkDevice
.
时激活的 扩展 或 Vulkan 功能而改变。
话虽如此:
Which implies that before allocating the memory for a buffer, you should have already created the buffer.
不正确。它要求您有答案并选择适合该答案的内存和字节偏移量。但是 Vulkan 对 "the answer" 的实际含义特别 松散 。
Vulkan 有 specific guarantees in place 可以让您知道特定 buffer/image 的答案,而不必询问 specific VkBuffer/Image
对象.细节有点复杂,但是对于缓冲区来说,它们是相当松散的。
基本思路是您可以创建一个测试VkBuffer/Image
并询问其内存属性。然后,您可以使用该答案来了解您打算使用的缓冲区的哪些属性 "similar" 。至少,Vulkan 保证两个相同的 buffer/image(格式、使用标志、大小等)将始终产生相同的内存属性。
但 Vulkan 还提供了一些其他保证。内存属性基本上告诉您 3 件事:
- 此对象可以绑定到的内存类型。
- 内存对象偏移量的对齐要求。
- 对象在内存中占用的字节大小。
对于尺寸,您只能得到最基本的保证:等效的 buffer/image 将产生等效的尺寸。
对于对齐,图像与大小一样严格:只有等效图像才能保证产生等效对齐。但是对于缓冲区来说,事情就更宽松了。如果测试缓冲区仅在使用标志上有所不同,而最终缓冲区使用使用标志的子集,则最终缓冲区的对齐不会比测试缓冲区更严格。所以你可以使用测试缓冲区的比对。
对于内存类型,事情就更加松散了。对于图像,唯一重要的是:
- 平铺
- 某些内存标志(sparse/split-instance 绑定)
- 图片格式是彩色还是depth/stencil
- 如果图像格式为depth/stencil,则格式必须匹配
- 外部存储器
- 瞬态分配用法
如果两个 VkImage
对象的所有这些都相同,则标准保证所有这些图像将支持同一组内存类型。
对于缓冲区,事情更加宽松。对于非稀疏缓冲区,如果您的测试缓冲区仅在使用标志方面与最终缓冲区不同,那么如果最终缓冲区具有测试缓冲区的使用标志的子集,则它支持的内存类型集必须包括所有来自测试缓冲区的。最终缓冲区可以支持更多,但它必须至少支持这样的测试缓冲区。
哦,线性图像和缓冲区必须始终能够在至少一种可映射的、连贯的内存类型中使用。当然,这要求您已经使用这些用法和标志字段创建了一个有效的 VkDevice/Image
,因此如果设备不允许(例如)将线性图像用作纹理,那么在询问之前它会停止关于内存属性。
- 有没有一种方法可以为
VkMemoryRequirements
结构获取正确的值,而无需先分配缓冲区且无需使用vkGetBufferMemoryRequirements
? - 是supported/compliant吗
动机 - 简短版
我有一个应用程序执行以下操作,并且一切正常。
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 规范指出:
memory must have been allocated using one of the memory types allowed in the memoryTypeBits member of the VkMemoryRequirements structure returned from a call to vkGetBufferMemoryRequirements with buffer
这意味着在为缓冲区分配内存之前,您应该已经创建了缓冲区。
我感觉在某些情况下,在您实际需要之前预分配一块内存会很有用;在我体验过的大多数 OpenGL 风格中,这是不可能的,但是 Vulkan 不应该受到这个限制,对吧?
- 在创建第一个缓冲区之前是否有一种(或多或少是自动的)方法来获取内存需求?
- 是supported/compliant吗?
显然,当您 do 为第一个缓冲区分配内存时,您可以分配更多的内存,这样当您需要第二个缓冲区时,您可以将它绑定到相同的块。但我的理解是,为了符合规范,您仍然需要在第二个缓冲区上调用 vkGetBufferMemoryRequirements
,即使它与第一个缓冲区的类型和大小完全相同。
本题已经识别答案为"no";你似乎只是想围绕你已经知道的事情做一个结束-运行。你不能。
您使用硬编码值显示的代码有效,因为您已经知道答案。并不是 Vulkan 要求您提出问题;而是Vulkan 要求您提供使用答案的缓冲区。
但是,由于 "the answer" 是特定于实现的,因此它会根据硬件而变化。当您安装新的驱动程序时,它可能会发生变化。事实上,它甚至可以根据您在创建 VkDevice
.
话虽如此:
Which implies that before allocating the memory for a buffer, you should have already created the buffer.
不正确。它要求您有答案并选择适合该答案的内存和字节偏移量。但是 Vulkan 对 "the answer" 的实际含义特别 松散 。
Vulkan 有 specific guarantees in place 可以让您知道特定 buffer/image 的答案,而不必询问 specific VkBuffer/Image
对象.细节有点复杂,但是对于缓冲区来说,它们是相当松散的。
基本思路是您可以创建一个测试VkBuffer/Image
并询问其内存属性。然后,您可以使用该答案来了解您打算使用的缓冲区的哪些属性 "similar" 。至少,Vulkan 保证两个相同的 buffer/image(格式、使用标志、大小等)将始终产生相同的内存属性。
但 Vulkan 还提供了一些其他保证。内存属性基本上告诉您 3 件事:
- 此对象可以绑定到的内存类型。
- 内存对象偏移量的对齐要求。
- 对象在内存中占用的字节大小。
对于尺寸,您只能得到最基本的保证:等效的 buffer/image 将产生等效的尺寸。
对于对齐,图像与大小一样严格:只有等效图像才能保证产生等效对齐。但是对于缓冲区来说,事情就更宽松了。如果测试缓冲区仅在使用标志上有所不同,而最终缓冲区使用使用标志的子集,则最终缓冲区的对齐不会比测试缓冲区更严格。所以你可以使用测试缓冲区的比对。
对于内存类型,事情就更加松散了。对于图像,唯一重要的是:
- 平铺
- 某些内存标志(sparse/split-instance 绑定)
- 图片格式是彩色还是depth/stencil
- 如果图像格式为depth/stencil,则格式必须匹配
- 外部存储器
- 瞬态分配用法
如果两个 VkImage
对象的所有这些都相同,则标准保证所有这些图像将支持同一组内存类型。
对于缓冲区,事情更加宽松。对于非稀疏缓冲区,如果您的测试缓冲区仅在使用标志方面与最终缓冲区不同,那么如果最终缓冲区具有测试缓冲区的使用标志的子集,则它支持的内存类型集必须包括所有来自测试缓冲区的。最终缓冲区可以支持更多,但它必须至少支持这样的测试缓冲区。
哦,线性图像和缓冲区必须始终能够在至少一种可映射的、连贯的内存类型中使用。当然,这要求您已经使用这些用法和标志字段创建了一个有效的 VkDevice/Image
,因此如果设备不允许(例如)将线性图像用作纹理,那么在询问之前它会停止关于内存属性。