Vulkan 在内存方面识别出两个不同的概念。有设备可以与之通信的实际物理 RAM 块。然后有一些方法可以从这些 RAM 池之一分配内存。
堆代表一块特定的 RAM。VkMemoryHeap
是描述设备可以与之通信的可用 RAM 堆之一的对象。真正定义特定堆的东西并不多。只有两个:RAM 存储的字节数和存储相对于 Vulkan 设备的位置(本地与非本地)。
内存类型是从特定堆分配内存的特定方式。VkMemoryType
是描述分配内存的特定方式的对象。对于如何从堆中分配内存,还有更多描述性标志。
举一个更具体的例子,考虑一个带有独立 GPU 的标准 PC 设置。该设备有自己的本地 RAM,但独立 GPU 也可以访问 CPU 内存。因此,Vulkan 设备将有两个堆:其中一个是本地的,另一个是非本地的。
但是,通常会有两种以上的内存类型。您通常有一种表示本地内存的内存类型,它没有VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
集合。这意味着您无法映射内存。您只能通过其他内存类型(或渲染操作或其他)的传输操作来访问它。
但是您通常会有两种内存类型,它们都使用相同的非本地堆。它们都是VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
,因此允许映射。但是,其中一个可能会VK_MEMORY_PROPERTY_HOST_CACHED_BIT
设置标志,而另一个将是VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
. 这允许您选择是否需要缓存 CPU 访问(因此需要显式刷新已修改内存范围)或非缓存 CPU 访问。
但是虽然它们是两种不同的内存类型,但它们都从同一个堆中分配。这就是为什么VkMemoryType
有一个索引指向分配它的内存的堆。
我唯一没有得到的是这两个DEVICE_LOCAL
标志是如何相互作用的。
你看规范了吗?它并没有完全隐藏它是如何工作的:
如果设置propertyFlags
了该VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
位,则分配给这种类型的内存对于设备访问是最有效的。此属性只会为属于具有该集合的堆的内存类型VK_MEMORY_HEAP_DEVICE_LOCAL_BIT
设置。
是说如果内存是本地的,那么与该内存对应的所有类型都是本地的,还是说它们可以是本地的?
您似乎试图对这些事情施加错误的含义。只需看一下规范所说的内容,并从表面上看。
PROPERTY_DEVICE_LOCAL
表示将实现最佳设备访问性能的内存类型。这和之间的唯一联系MEMORY_DEVICE_LOCAL
是,内存类型PROPERTY_DEVICE_LOCAL
仅与使用 的内存堆相关联MEMORY_DEVICE_LOCAL
。
这是这里唯一相关的含义。
如果您想要一个内存堆何时是设备本地的示例,但具有不是的内存类型,请考虑一个没有自己内存的 GPU。只有一个堆,因此是MEMORY_DEVICE_LOCAL
.
但是,以使其主机可见的方式从该池分配内存可能会降低设备访问该内存的性能。因此,对于这样的硬件,同一堆的主机可见内存类型将不会使用PROPERTY_DEVICE_LOCAL
。
再说一次,其他硬件不会因为使内存主机可见而失去性能。所以它们只有一种内存类型,它具有所有可用属性。对于英特尔来说,他们的片上 GPU 显然可以访问某种级别的 CPU 缓存。