22VulKan——内存管理

1.内存

 VulKan将内存分为两类:Host Memory 和 Device Memory.

Host是运行应用程序的处理器,在PC端上就是指CPU;Device是执行VulKan命令的处理器,也就是GPU.

Host memory指的是对Host可见的内存,Device memory指的是对Device可见的内存。 在使用Host Memory时,一定要注意内存对齐。不允许简单的直接把malloc hook到Vulkan的内存分配函数上!

更详细的,Vulkan系统中的内存有四种类型:

  • Host Local Memory,只对Host可见的内存,通常称之为普通内存
  • Device Local Memory,只对Device可见的内存,通常称之为显存
  • Host Local Device Memory,由Host管理的,对Device看见的内存
  • Device Local Host Memory,由Device管理的,对Host可见的内存

其中,不同内存类型适用不同场景:

  • Device Local Memory适合优先级最高的资源,通常是纹理等频繁被使用的渲染数据。当内存空间不够时我们才会考虑是否将这些内存数据放到CPU端。
  • Device Local Host Memory 适合CPU 到 GPU的数据传递一些顶点数据等,可以通过这种方式传递。
  • Host Local Device Memory 适合GPU 到 CPU的数据传递,截图、回写等操作可以使用这种内存。

并不是所有设备都支持这四种类型。一些嵌入式系统、移动设备甚至是笔记本电脑的GPU,可能与CPU共享内存控制器和内存子系统。这种情况它的内存只有一种类型,通常称之为unified memory architecture(统一内存架构)。

1.1 Host Memory

Host Memory是CPU可以访问的常规内存,一般是通过调用malloc或new分配。

Vulkan API创建的对象通常需要一定数量的Host Memory,用来储存对象和数据结构。

Vulkan对Host Memory的要求就是内存地址是对齐的!

这是因为某些高性能CPU指令在对齐的内存地址上效果最佳。通过假定存储CPU端数据结构的分配是对齐的,Vulkan可以无条件使用这些高性能指令,从而提供显著的性能优势。

1.2 Device Memory

任何可以由Device访问的内存,都被称为Device Memory(设备内存)。Device Memory距离Device更近,比Host Memory更有性能优势。Image object、Buffer object、UBO(uniform buffer objec)都由Device Memory分配。Vulkan中的所有资源都由Device Memory支持。

1.3 内存池Pool

内存是一种昂贵的资源,分配操作通常会有间接的系统代价。

Vulkan中通过资源池来平摊成本,一些创建比较频繁的资源都由资源池统一管理

  • Command Buffer Pool
  • Descriptor Pool
  • Query Pool

2. Buffer and Resources

内存的作用是给资源做底层支持,不同的资源对内存的要求并不一样。

Vulkan有两种基本资源类型:Buffer和Image。

 

Buffer 是最简单的资源类型,可以用来储存线性的结构化的数据,也可以储存内存中原始字节。

从图中我们可以看到,vulkan中使用的buffer类型主要有:

  • indirect buffer
  • index buffer
  • vertex buffer
  • uniform texel buffer
  • uniform buffer
  • storage texel buffer
  • storage buffer

当使用vkCreateBuffer创建一个buffer对象的时候,在创建信息VkBufferCreateInfo中,就要指定这个buffer对象可能的使用场景。除了上述七种有着一一对应的使用掩码位之外,还有额外的两个,分别表示buffer是否可以作为transfer的src或者dst。当创建好了一个buffer对象后,需要将它和一个memory对象关联起来,这样才可以真正让这个buffer对象拥有memory。关联是通过vkBindBufferMemory来完成的,然而,直接binding可能会失败,因为创建的buffer可能会有一些额外的要求,例如对齐等,所以在此之前,需要使用vkGetBufferMemoryRequirements来获取这个buffer对象对于memory等要求。要求被填入一个VkMemoryRequirements的对象中

Image 则相对比较复杂,具有特殊的布局(layout)和格式(format),可用来做flitering,blending,depth 和 stencil testing等。 从vulkan pipeline中,可以看出,image主要是作为shader resource的sampled image(即传统意义上的texture),storage image,以及frame buffer中的input attachment, color attachment和depth/stencil attachment。

Image的布局(layout)对内存有特殊需求,主要有两种主要的平铺模式(tiling modes):

  • linear - 其中的图像(Image)数据线性的排列在内存中。
  • optimal - 其中的图像(Image)数据以高度优化的模式进行布局,可以有效利用设备的内存子系统。

线性布局(linear layout)适合连续的单行的读写,但是大多数图形操作都涉及到跨行读写纹理元素(比如在计算A时,需要参考ABCD四个纹理像素),如果图像的宽度非常宽,相邻行的访问在线性布局中会有非常大的跳转。这可能会导致性能问题。

优化布局(optimal layout)的好处是内存数据根据不同内存子系统进行优化,比如将所有的纹理像素都优化到一块连续的内存区域中,加快内存处理速度。

GPU硬件通常倾向于使用优化布局以实现更有效的渲染。但是优化布局(optimal layout)通常是“不透明的”,这意味着优化布局格式的详细信息不会被其他需要读取或写入图像数据的组件得知。

如果CPU如果想读取生层的图像信息,图像在被读取之前要进行布局转换,将optimal layout转换为普通布局后,CPU才能正确识别图像信息。

内存销毁

一个memory对象在生命周期的尽头,由vkFreeMemory释放。   当释放一个memory对象的时候,app应当保证此时device不再引用此memory对象上所关联的image/buffer。 app可以使用vkMapMemory(3)来获取cpu侧的指针以访问其中的内容,然后使用vkUnmapMemory(3)来释放

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章