共享堆

共享对于多进程和多适配器体系结构非常有用。

共享概述

共享堆支持以下两项:在一个或多个进程之间共享堆中的数据,以及排除放置在堆中的资源的未定义纹理布局的非确定性选择。 在适配器之间共享堆也无需对数据进行 CPU 封送。

可以共享堆和提交的资源。 共享提交的资源实际上是共享隐式堆以及提交的资源说明,以便可以将兼容的资源说明从其他设备映射到堆。

所有方法都是自由线程,并继承 NT 句柄共享设计的现有 D3D11 语义。

在进程之间共享堆

共享堆是使用 D3D12_HEAP_FLAGS 枚举的 D3D12_HEAP_FLAG_SHARED 成员指定的。

共享堆在可访问 CPU 的堆上不受支持:没有D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE的D3D12_HEAP_TYPE_UPLOAD、D3D12_HEAP_TYPE_READBACK和D3D12_HEAP_TYPE_CUSTOM。

排除未定义纹理布局的非确定性选择可能会显著损害某些 GPU 上的延迟呈现情况,因此这不是放置和提交的资源的默认行为。 延迟呈现在某些 GPU 体系结构上受损,因为确定性纹理布局减少在同时呈现到格式和大小相同的多个呈现器目标纹理时获得的有效内存带宽。 GPU 体系结构正在演变为不使用非确定性纹理布局,以便有效地支持延迟呈现的标准化重排模式和标准化布局。

共享堆也附带其他少量成本:

  • 由于信息泄露问题,共享堆数据无法像进程内堆那样灵活回收,因此物理内存更频繁地为零。
  • 在创建和销毁共享堆期间,附加了少量 CPU 开销并增加了系统内存使用量。

跨适配器共享堆

使用 D3D12_HEAP_FLAGS 枚举的 D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER 成员指定跨适配器的共享堆。

通过跨适配器的共享堆,多个适配器可以在不对其中的数据进行 CPU 封送的情况下共享数据。 虽然不同的适配器功能可以确定适配器传递其中的数据的效率,但仅启用 GPU 副本即可增加获得的有效带宽。 跨适配器堆上允许某些纹理布局,以支持纹理数据交换,即使不支持此类纹理布局也是如此。 某些限制可能适用于此类纹理,例如仅支持复制。

跨适配器共享适用于通过调用 ID3D12Device::CreateHeap 而创建的堆。 然后,应用程序可以通过 CreatePlacedResource 创建资源。 CreateCommittedResource 创建的资源/堆也允许它,但仅适用于 (引用D3D12_RESOURCE_DIMENSION) 的行主D3D12_RESOURCE_DIMENSION_TEXTURE2D资源。 跨适配器共享并不适用于 CreateReservedResource

对于跨适配器共享,所有常用跨队列资源共享规则仍适用。 应用程序必须发出适当的屏障,以确保两个适配器之间的正确同步和一致性。 应用程序应使用跨适配器围栏来协调提交到多个适配器的命令列表的计划。 没有用于在 D3D API 版本之间共享跨适配器资源的机制。 系统内存中仅支持跨适配器共享资源。 使用 L0 内存池 (的D3D12_HEAP_TYPE_DEFAULT堆和D3D12_HEAP_TYPE_CUSTOM堆支持跨适配器共享堆/资源,) 写合并 CPU 页属性。 驱动程序必须确保对跨适配器共享堆执行的 GPU 读/写操作与系统上的其他 GPU 一致。 例如,驱动程序可能需要排除驻留在 CPU 无法直接访问堆数据时通常不需要刷新的 GPU 缓存中的堆数据。

应用程序应将跨适配器堆的使用限制为仅那些需要它们提供的功能的方案。 跨适配器堆位于 D3D12_MEMORY_POOL_L0,这并不总是 GetCustomHeapProperties 所建议的。 该内存池不适用于离散/NUMA 适配器体系结构。 最高效的纹理布局并不总是可用。

还存在下列限制:

  • 必须与堆层相关的堆标志D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES。
  • 还必须设置D3D12_HEAP_FLAG_SHARED。
  • 必须设置D3D12_HEAP_TYPE_DEFAULT或使用D3D12_MEMORY_POOL_L0 D3D12_HEAP_TYPE_CUSTOM,并且必须设置D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE。
  • 只能将具有D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER的资源放置在跨适配器堆上。
  • 指定D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER时,无法将受保护的会话传递到堆的创建中

有关使用多个适配器的详细信息,请参阅 多适配器系统 部分。