内存分配

Vulkan 内存分为两种类型:主机内存设备内存

主机内存

主机内存是 Vulkan 实现所需的,用于非设备可见的存储。

此内存 可能 用于存储 Vulkan 对象的实现表示和状态。

Vulkan 为应用程序提供了代表 Vulkan 实现执行主机内存分配的机会。 如果不使用此功能,则实现将执行自己的内存分配。 由于大多数内存分配不在关键路径上,因此这并非旨在作为性能功能。 相反,这 可以 对某些嵌入式系统、调试目的(例如,在所有主机分配后放置一个保护页)或内存分配日志记录很有用。

分配器由应用程序以指向 VkAllocationCallbacks 结构的指针形式提供

// Provided by VK_VERSION_1_0
typedef struct VkAllocationCallbacks {
    void*                                   pUserData;
    PFN_vkAllocationFunction                pfnAllocation;
    PFN_vkReallocationFunction              pfnReallocation;
    PFN_vkFreeFunction                      pfnFree;
    PFN_vkInternalAllocationNotification    pfnInternalAllocation;
    PFN_vkInternalFreeNotification          pfnInternalFree;
} VkAllocationCallbacks;
  • pUserData 是一个值,由回调的实现来解释。 当调用 VkAllocationCallbacks 中的任何回调时,Vulkan 实现将此值作为回调的第一个参数传递。 此值 可以 在每次将分配器传递到命令时发生变化,即使同一对象在多个命令中采用分配器也是如此。

  • pfnAllocation 是指向应用程序定义的内存分配函数的 PFN_vkAllocationFunction 指针。

  • pfnReallocation 是指向应用程序定义的内存重新分配函数的 PFN_vkReallocationFunction 指针。

  • pfnFree 是指向应用程序定义的内存释放函数的 PFN_vkFreeFunction 指针。

  • pfnInternalAllocation 是指向应用程序定义的函数的 PFN_vkInternalAllocationNotification 指针,当实现进行内部分配时,将调用该函数。

  • pfnInternalFree 是指向应用程序定义的函数的 PFN_vkInternalFreeNotification 指针,当实现释放内部分配时,将调用该函数。

有效用法
  • VUID-VkAllocationCallbacks-pfnAllocation-00632
    pfnAllocation 必须 是指向有效的应用程序定义的 PFN_vkAllocationFunction 的有效指针

  • VUID-VkAllocationCallbacks-pfnReallocation-00633
    pfnReallocation 必须 是指向有效的应用程序定义的 PFN_vkReallocationFunction 的有效指针

  • VUID-VkAllocationCallbacks-pfnFree-00634
    pfnFree 必须 是指向有效的应用程序定义的 PFN_vkFreeFunction 的有效指针

  • VUID-VkAllocationCallbacks-pfnInternalAllocation-00635
    如果 pfnInternalAllocationpfnInternalFree 中任何一个不是 NULL,则两者 必须 是有效的回调

pfnAllocation 的类型为

// Provided by VK_VERSION_1_0
typedef void* (VKAPI_PTR *PFN_vkAllocationFunction)(
    void*                                       pUserData,
    size_t                                      size,
    size_t                                      alignment,
    VkSystemAllocationScope                     allocationScope);
  • pUserData 是应用程序指定的分配器中 VkAllocationCallbacks::pUserData 指定的值。

  • size 是请求的分配的字节大小。

  • alignment 是请求的分配对齐方式(以字节为单位),并且 必须 是 2 的幂。

  • allocationScope 是一个 VkSystemAllocationScope 值,指定分配生存期的分配范围,如此处所述。

如果 pfnAllocation 无法分配请求的内存,则 必须 返回 NULL。 如果分配成功,则 必须 返回指向至少包含 size 字节的内存分配的有效指针,并且指针值是 alignment 的倍数。

如果应用程序不遵循这些规则,则 无法 假定 Vulkan 操作正确。

例如,pfnAllocation(或 pfnReallocation)可能会由于调试目的,直接或间接地导致运行中的 Vulkan 实例在分配失败时终止。 在这种情况下,不能 假定任何受影响的 VkInstance 对象的任何部分都可以正常工作(甚至 vkDestroyInstance),并且应用程序 必须 确保通过其他方式(例如,进程终止)进行正确清理。

如果 pfnAllocation 返回 NULL,并且如果实现无法在没有请求的分配的情况下继续正确处理当前命令,则必须将其视为运行时错误,并在检测到该情况的命令的适当时间生成 VK_ERROR_OUT_OF_HOST_MEMORY,如 返回码 中所述。

如果实现能够在没有请求的分配的情况下继续正确处理当前命令,则可以这样做,并且不得因分配失败而生成 VK_ERROR_OUT_OF_HOST_MEMORY

pfnReallocation 的类型是

// Provided by VK_VERSION_1_0
typedef void* (VKAPI_PTR *PFN_vkReallocationFunction)(
    void*                                       pUserData,
    void*                                       pOriginal,
    size_t                                      size,
    size_t                                      alignment,
    VkSystemAllocationScope                     allocationScope);
  • pUserData 是应用程序指定的分配器中 VkAllocationCallbacks::pUserData 指定的值。

  • pOriginal 必须NULL,或者是指向先前由兼容分配器的 pfnReallocationpfnAllocation 返回的指针。

  • size 是请求的分配的字节大小。

  • alignment 是请求的分配对齐方式(以字节为单位),并且 必须 是 2 的幂。

  • allocationScope 是一个 VkSystemAllocationScope 值,指定分配生存期的分配范围,如此处所述。

如果重新分配成功,pfnReallocation 必须返回具有足够空间容纳 size 字节的分配,并且原始分配中从零字节到 min(原始大小, 新大小) - 1 的内容必须保留在返回的分配中。如果 size 大于旧大小,则额外空间的内容是未定义的。如果满足这些要求涉及创建新的分配,则应释放旧的分配。

如果 pOriginalNULL,则 pfnReallocation 必须表现得等同于使用相同参数值(不包括 pOriginal)调用 PFN_vkAllocationFunction

如果 size 为零,则 pfnReallocation 必须表现得等同于使用相同的 pUserData 参数值且 pMemory 等于 pOriginal 调用 PFN_vkFreeFunction

如果 pOriginal 不为 NULL,则实现必须确保 alignment 等于最初分配 pOriginal 时使用的 alignment

如果此函数失败且 pOriginal 不为 NULL,则应用程序不得释放旧的分配。

pfnReallocation 必须遵循与 PFN_vkAllocationFunction 相同的返回值规则

pfnFree 的类型是

// Provided by VK_VERSION_1_0
typedef void (VKAPI_PTR *PFN_vkFreeFunction)(
    void*                                       pUserData,
    void*                                       pMemory);
  • pUserData 是应用程序指定的分配器中 VkAllocationCallbacks::pUserData 指定的值。

  • pMemory 是要释放的分配。

pMemory 可以NULL,回调必须安全地处理这种情况。如果 pMemory 不为 NULL,则它必须是先前由 pfnAllocationpfnReallocation 分配的指针。应用程序应该释放此内存。

pfnInternalAllocation 的类型是

// Provided by VK_VERSION_1_0
typedef void (VKAPI_PTR *PFN_vkInternalAllocationNotification)(
    void*                                       pUserData,
    size_t                                      size,
    VkInternalAllocationType                    allocationType,
    VkSystemAllocationScope                     allocationScope);

这是一个纯粹的信息性回调。

pfnInternalFree 的类型是

// Provided by VK_VERSION_1_0
typedef void (VKAPI_PTR *PFN_vkInternalFreeNotification)(
    void*                                       pUserData,
    size_t                                      size,
    VkInternalAllocationType                    allocationType,
    VkSystemAllocationScope                     allocationScope);

每个分配都有一个分配范围,定义其生命周期以及它与哪个对象相关联。传递给 VkAllocationCallbacks 指定的回调函数的 allocationScope 参数的可能值(指示分配范围)是

// Provided by VK_VERSION_1_0
typedef enum VkSystemAllocationScope {
    VK_SYSTEM_ALLOCATION_SCOPE_COMMAND = 0,
    VK_SYSTEM_ALLOCATION_SCOPE_OBJECT = 1,
    VK_SYSTEM_ALLOCATION_SCOPE_CACHE = 2,
    VK_SYSTEM_ALLOCATION_SCOPE_DEVICE = 3,
    VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE = 4,
} VkSystemAllocationScope;
  • VK_SYSTEM_ALLOCATION_SCOPE_COMMAND 指定分配的范围是 Vulkan 命令的持续时间。

  • VK_SYSTEM_ALLOCATION_SCOPE_OBJECT 指定分配的范围是正在创建或使用的 Vulkan 对象的生命周期。

  • VK_SYSTEM_ALLOCATION_SCOPE_CACHE 指定分配的范围是 VkPipelineCacheVkValidationCacheEXT 对象的生命周期。

  • VK_SYSTEM_ALLOCATION_SCOPE_DEVICE 指定分配的范围是 Vulkan 设备的生命周期。

  • VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE 指定分配的范围是 Vulkan 实例的生命周期。

大多数 Vulkan 命令都对单个对象进行操作,或者存在正在创建或操作的唯一对象。当分配使用 VK_SYSTEM_ALLOCATION_SCOPE_OBJECTVK_SYSTEM_ALLOCATION_SCOPE_CACHE 的分配范围时,该分配的范围是正在创建或操作的对象。

当实现需要主机内存时,它将使用最可用的特定分配器和分配范围回调应用程序

  • 如果分配的范围是命令的持续时间,则分配器将使用 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND 分配范围。使用最可用的特定分配器:如果要创建或操作的对象具有分配器,则将使用该对象的分配器;否则,如果父 VkDevice 具有分配器,则将使用该分配器;否则,如果父 VkInstance 具有分配器,则将使用该分配器。否则,

  • 如果分配与 VkValidationCacheEXTVkPipelineCache 对象相关联,则分配器将使用 VK_SYSTEM_ALLOCATION_SCOPE_CACHE 分配范围。使用最可用的特定分配器(缓存,否则设备,否则实例)。否则,

  • 如果分配的范围是对象的生命周期,则该对象正在被命令创建或操作,并且该对象的类型不是 VkDeviceVkInstance,则分配器将使用 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT 的分配范围。使用最可用的特定分配器(对象,否则设备,否则实例)。否则,

  • 如果分配的范围是设备的生命周期,则分配器将使用 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE 的分配范围。使用最可用的特定分配器(设备,否则实例)。否则,

  • 如果分配的范围是实例的生命周期,并且该实例具有分配器,则将使用其分配器,其分配范围为 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE

  • 否则,实现将通过未指定的替代机制分配内存。

从池中分配的对象不指定它们自己的分配器。当实现需要此类对象的主机内存时,该内存来自对象的父池的分配器。

由于不同平台之间安全实现的复杂性,应用程序不应处理旨在由主机执行的内存的分配。实现将在内部分配此类内存,并在分配和释放这些内部分配时调用应用程序提供的信息性回调。分配可执行内存后,将调用 pfnInternalAllocation。释放可执行内存后,将调用 pfnInternalFree。实现只会为可执行内存的分配和释放调用信息性回调。

pfnInternalAllocationpfnInternalFree 函数的 allocationType 参数可能是以下值之一

// Provided by VK_VERSION_1_0
typedef enum VkInternalAllocationType {
    VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE = 0,
} VkInternalAllocationType;
  • VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE 指定分配旨在由主机执行。

在执行 API 命令期间,实现必须仅调用应用程序提供的分配器。实现必须仅从调用发起 API 命令的同一线程调用应用程序提供的分配器。实现应该不同步对任何回调的调用。如果需要同步,回调必须自行提供。信息回调与分配回调受到相同的限制。

如果实现在 vkCreate* 命令返回和对应的 vkDestroy* 命令开始之间的时间内打算通过 VkAllocationCallbacks 结构进行调用,则该实现必须vkCreate* 命令返回之前保存分配器的副本。回调函数及其所依赖的任何数据结构,在它们所关联的对象的生命周期内必须保持有效。

如果向 vkCreate* 命令提供了分配器,则必须向对应的 vkDestroy* 命令提供一个兼容的分配器。如果使用每个结构中的 pfnAllocationpfnReallocation 分配的内存可以使用另一个结构中的 pfnReallocationpfnFree 释放,则两个 VkAllocationCallbacks 结构是兼容的。如果没有向对应的 vkCreate* 命令提供分配器,则必须不向 vkDestroy* 命令提供分配器。

如果使用非 NULL 分配器,则 pfnAllocationpfnReallocationpfnFree 成员必须为非 NULL,并指向回调的有效实现。应用程序可以选择不提供信息回调,方法是将 pfnInternalAllocationpfnInternalFree 都设置为 NULLpfnInternalAllocationpfnInternalFree 必须要么都为 NULL,要么都为非 NULL

如果 pfnAllocationpfnReallocation 失败,则实现可能会使对象创建失败和/或生成 VK_ERROR_OUT_OF_HOST_MEMORY 错误(如适用)。

分配回调必须不调用任何 Vulkan 命令。

以下规则集定义了实现何时可以调用分配器回调。

pfnAllocationpfnReallocation 可能在以下情况下被调用:

  • 作用域为 VkDeviceVkInstance 的分配可能从任何 API 命令中分配。

  • 作用域为命令的分配可能从任何 API 命令中分配。

  • 作用域为 VkPipelineCache 的分配可能仅从以下命令中分配:

    • vkCreatePipelineCache

    • vkMergePipelineCaches,针对 dstCache

    • vkCreateGraphicsPipelines,针对 pipelineCache

    • vkCreateComputePipelines,针对 pipelineCache

  • 作用域为 VkValidationCacheEXT 的分配可能仅从以下命令中分配:

  • 作用域为 VkDescriptorPool 的分配可能仅从以下命令中分配:

    • 任何将池作为直接参数的命令

    • vkAllocateDescriptorSets,针对其 pAllocateInfo 参数的 descriptorPool 成员

    • vkCreateDescriptorPool

  • 作用域为 VkCommandPool 的分配可能仅从以下命令中分配:

    • 任何将池作为直接参数的命令

    • vkCreateCommandPool

    • vkAllocateCommandBuffers,针对其 pAllocateInfo 参数的 commandPool 成员

    • 任何 vkCmd* 命令,其 commandBuffer 是从该 VkCommandPool 分配的

  • 作用域为任何其他对象的分配可能仅在该对象的 vkCreate* 命令中分配。

pfnFreepfnReallocationsize 为零)可能在以下情况下被调用:

  • 作用域为 VkDeviceVkInstance 的分配可能从任何 API 命令中释放。

  • 作用域为命令的分配必须由分配此类内存的任何 API 命令释放。

  • 作用域为 VkPipelineCache 的分配可能vkDestroyPipelineCache 中释放。

  • 作用域为 VkValidationCacheEXT 的分配可能vkDestroyValidationCacheEXT 中释放。

  • 作用域为 VkDescriptorPool 的分配可能从以下命令中释放:

    • 任何将池作为直接参数的命令

  • 作用域为 VkCommandPool 的分配可能从以下命令中释放:

    • 任何将池作为直接参数的命令

    • vkResetCommandBuffer,其 commandBuffer 是从该 VkCommandPool 分配的

  • 作用域为任何其他对象的分配可能在该对象的 vkDestroy* 命令中释放。

  • 任何分配主机内存的命令可能也会释放相同作用域的主机内存。

设备内存

设备内存是设备可见的内存 — 例如,图像或缓冲区对象的内容,这些内容可以由设备本地使用。

设备内存属性

物理设备的内存属性描述了可用的内存堆和内存类型。

要查询内存属性,请调用

// Provided by VK_VERSION_1_0
void vkGetPhysicalDeviceMemoryProperties(
    VkPhysicalDevice                            physicalDevice,
    VkPhysicalDeviceMemoryProperties*           pMemoryProperties);
有效使用(隐式)
  • VUID-vkGetPhysicalDeviceMemoryProperties-physicalDevice-parameter
    physicalDevice 必须是有效的 VkPhysicalDevice 句柄

  • VUID-vkGetPhysicalDeviceMemoryProperties-pMemoryProperties-parameter
    pMemoryProperties 必须是指向 VkPhysicalDeviceMemoryProperties 结构的有效指针

VkPhysicalDeviceMemoryProperties 结构定义为

// Provided by VK_VERSION_1_0
typedef struct VkPhysicalDeviceMemoryProperties {
    uint32_t        memoryTypeCount;
    VkMemoryType    memoryTypes[VK_MAX_MEMORY_TYPES];
    uint32_t        memoryHeapCount;
    VkMemoryHeap    memoryHeaps[VK_MAX_MEMORY_HEAPS];
} VkPhysicalDeviceMemoryProperties;
  • memoryTypeCountmemoryTypes 数组中有效元素的数量。

  • memoryTypesVK_MAX_MEMORY_TYPESVkMemoryType 结构的数组,描述了可以用于访问从 memoryHeaps 指定的堆分配的内存的内存类型

  • memoryHeapCountmemoryHeaps 数组中有效元素的数量。

  • memoryHeapsVK_MAX_MEMORY_HEAPSVkMemoryHeap 结构的数组,描述了从中可以分配内存的内存堆

VkPhysicalDeviceMemoryProperties 结构描述了多个内存堆以及多个可用于访问这些堆中分配的内存的内存类型。 每个堆描述特定大小的内存资源,每个内存类型描述一组可用于给定内存堆的内存属性(例如,主机缓存与非缓存)。 使用特定内存类型的分配将消耗该内存类型堆索引所指示的堆中的资源。 多个内存类型可能共享每个堆,堆和内存类型提供了一种机制,在允许内存与各种不同属性一起使用的同时,也能展示物理内存资源的准确大小。

内存堆的数量由 memoryHeapCount 给出,且小于等于 VK_MAX_MEMORY_HEAPS。每个堆由 memoryHeaps 数组的元素以 VkMemoryHeap 结构的形式描述。所有内存堆可用的内存类型数量由 memoryTypeCount 给出,且小于等于 VK_MAX_MEMORY_TYPES。每个内存类型由 memoryTypes 数组的元素以 VkMemoryType 结构的形式描述。

至少一个堆的 VkMemoryHeap::flags必须包含 VK_MEMORY_HEAP_DEVICE_LOCAL_BIT。 如果多个堆都具有相似的性能特征,它们都可以包含 VK_MEMORY_HEAP_DEVICE_LOCAL_BIT。 在统一内存架构 (UMA) 系统中,通常只有一个内存堆被认为对主机和设备都同样“本地”,并且这样的实现必须将该堆标记为设备本地。

通过 vkGetPhysicalDeviceMemoryProperties 返回的每个内存类型的 propertyFlags 必须设置为以下值之一

  • 0

  • VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT

  • VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
    VK_MEMORY_PROPERTY_HOST_CACHED_BIT

  • VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
    VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT

  • VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT

  • VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT

  • VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
    VK_MEMORY_PROPERTY_HOST_CACHED_BIT

  • VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
    VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT

  • VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
    VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT

  • VK_MEMORY_PROPERTY_PROTECTED_BIT

  • VK_MEMORY_PROPERTY_PROTECTED_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT

  • VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
    VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD

  • VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
    VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
    VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD

  • VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
    VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD

  • VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
    VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD

  • VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
    VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
    VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD

  • VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
    VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD |
    VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD

  • VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
    VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
    VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD |
    VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD

  • VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
    VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD |
    VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD

  • VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
    VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD |
    VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD

  • VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
    VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
    VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD |
    VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD

  • VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
    VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV

必须至少有一个内存类型的 propertyFlags 中同时设置了 VK_MEMORY_PROPERTY_HOST_VISIBLE_BITVK_MEMORY_PROPERTY_HOST_COHERENT_BIT 位。 必须至少有一个内存类型的 propertyFlags 中设置了 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT 位。 如果启用了 deviceCoherentMemory 功能,则必须至少有一个内存类型的 propertyFlags 中设置了 VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD 位。

对于 memoryTypes 中返回的每对元素 XY,如果满足以下条件,X 必须放置在比 Y 更低的索引位置:

  • XpropertyFlags 成员中返回的位标志集合是 YpropertyFlags 成员中返回的位标志集合的严格子集; 或者

  • XYpropertyFlags 成员相等,且 X 属于性能更高的内存堆(以特定于实现的方式确定); 或者

  • YpropertyFlags 成员包含 VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMDVK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD,而 X 不包含

如果 XYpropertyFlags 成员之间不是子集关系,则它们之间没有排序要求。 这可能会导致同组内存类型有多种可能的排序方式。 请注意,所有允许的内存属性标志组合的列表以有效的顺序编写。 但是,如果 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BITVK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT 之前,该列表仍然会是有效的顺序。

使用设备相干或非缓存设备内存类型可能会导致性能损失,而意外使用这些类型是不希望发生的。为了避免这种情况,具有这些属性的内存类型始终显示在列表的末尾; 但在其他方面仍遵循相同的规则。

这种排序要求使应用程序能够使用简单的搜索循环来选择所需的内存类型,例如:

// Find a memory in `memoryTypeBitsRequirement` that includes all of `requiredProperties`
int32_t findProperties(const VkPhysicalDeviceMemoryProperties* pMemoryProperties,
                       uint32_t memoryTypeBitsRequirement,
                       VkMemoryPropertyFlags requiredProperties) {
    const uint32_t memoryCount = pMemoryProperties->memoryTypeCount;
    for (uint32_t memoryIndex = 0; memoryIndex < memoryCount; ++memoryIndex) {
        const uint32_t memoryTypeBits = (1 << memoryIndex);
        const bool isRequiredMemoryType = memoryTypeBitsRequirement & memoryTypeBits;

        const VkMemoryPropertyFlags properties =
            pMemoryProperties->memoryTypes[memoryIndex].propertyFlags;
        const bool hasRequiredProperties =
            (properties & requiredProperties) == requiredProperties;

        if (isRequiredMemoryType && hasRequiredProperties)
            return static_cast<int32_t>(memoryIndex);
    }

    // failed to find memory type
    return -1;
}

// Try to find an optimal memory type, or if it does not exist try fallback memory type
// `device` is the VkDevice
// `image` is the VkImage that requires memory to be bound
// `memoryProperties` properties as returned by vkGetPhysicalDeviceMemoryProperties
// `requiredProperties` are the property flags that must be present
// `optimalProperties` are the property flags that are preferred by the application
VkMemoryRequirements memoryRequirements;
vkGetImageMemoryRequirements(device, image, &memoryRequirements);
int32_t memoryType =
    findProperties(&memoryProperties, memoryRequirements.memoryTypeBits, optimalProperties);
if (memoryType == -1) // not found; try fallback properties
    memoryType =
        findProperties(&memoryProperties, memoryRequirements.memoryTypeBits, requiredProperties);

VK_MAX_MEMORY_TYPES 是描述内存类型的 VkMemoryType 结构数组的长度,如 VkPhysicalDeviceMemoryProperties::memoryTypes 中返回的那样。

#define VK_MAX_MEMORY_TYPES               32U

VK_MAX_MEMORY_HEAPS 是描述内存堆的 VkMemoryHeap 结构数组的长度,如 VkPhysicalDeviceMemoryProperties::memoryHeaps 中返回的那样。

#define VK_MAX_MEMORY_HEAPS               16U

要查询内存属性,请调用

// Provided by VK_VERSION_1_1
void vkGetPhysicalDeviceMemoryProperties2(
    VkPhysicalDevice                            physicalDevice,
    VkPhysicalDeviceMemoryProperties2*          pMemoryProperties);

或等效命令

// Provided by VK_KHR_get_physical_device_properties2
void vkGetPhysicalDeviceMemoryProperties2KHR(
    VkPhysicalDevice                            physicalDevice,
    VkPhysicalDeviceMemoryProperties2*          pMemoryProperties);

vkGetPhysicalDeviceMemoryProperties2 的行为类似于 vkGetPhysicalDeviceMemoryProperties,但能够在输出结构的 pNext 链中返回扩展信息。

有效使用(隐式)
  • VUID-vkGetPhysicalDeviceMemoryProperties2-physicalDevice-parameter
    physicalDevice 必须是有效的 VkPhysicalDevice 句柄

  • VUID-vkGetPhysicalDeviceMemoryProperties2-pMemoryProperties-parameter
    pMemoryProperties 必须是指向 VkPhysicalDeviceMemoryProperties2 结构的有效指针

VkPhysicalDeviceMemoryProperties2 结构定义如下:

// Provided by VK_VERSION_1_1
typedef struct VkPhysicalDeviceMemoryProperties2 {
    VkStructureType                     sType;
    void*                               pNext;
    VkPhysicalDeviceMemoryProperties    memoryProperties;
} VkPhysicalDeviceMemoryProperties2;

或等效的

// Provided by VK_KHR_get_physical_device_properties2
typedef VkPhysicalDeviceMemoryProperties2 VkPhysicalDeviceMemoryProperties2KHR;
有效使用(隐式)
  • VUID-VkPhysicalDeviceMemoryProperties2-sType-sType
    sType 必须VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2

  • VUID-VkPhysicalDeviceMemoryProperties2-pNext-pNext
    pNext 必须NULL 或指向 VkPhysicalDeviceMemoryBudgetPropertiesEXT 的有效实例的指针

  • VUID-VkPhysicalDeviceMemoryProperties2-sType-unique
    pNext 链中每个结构的 sType必须是唯一的

VkMemoryHeap 结构定义如下:

// Provided by VK_VERSION_1_0
typedef struct VkMemoryHeap {
    VkDeviceSize         size;
    VkMemoryHeapFlags    flags;
} VkMemoryHeap;
  • size 是堆中内存的总大小(以字节为单位)。

  • flagsVkMemoryHeapFlagBits 的位掩码,指定堆的属性标志。

VkMemoryHeap::flags可以设置的位,指示堆的属性标志是

// Provided by VK_VERSION_1_0
typedef enum VkMemoryHeapFlagBits {
    VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0x00000001,
  // Provided by VK_VERSION_1_1
    VK_MEMORY_HEAP_MULTI_INSTANCE_BIT = 0x00000002,
  // Provided by VK_KHR_device_group_creation
    VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHR = VK_MEMORY_HEAP_MULTI_INSTANCE_BIT,
} VkMemoryHeapFlagBits;
  • VK_MEMORY_HEAP_DEVICE_LOCAL_BIT 指定堆对应于设备本地内存。 设备本地内存可能具有与主机本地内存不同的性能特征,并且可能支持不同的内存属性标志。

  • VK_MEMORY_HEAP_MULTI_INSTANCE_BIT 指定在表示多个物理设备的逻辑设备中,存在每个物理设备实例的堆内存。 默认情况下,从此类堆进行的分配将复制到每个物理设备的堆实例。

// Provided by VK_VERSION_1_0
typedef VkFlags VkMemoryHeapFlags;

VkMemoryHeapFlags 是用于设置零个或多个 VkMemoryHeapFlagBits 的掩码的位掩码类型。

VkMemoryType 结构定义如下:

// Provided by VK_VERSION_1_0
typedef struct VkMemoryType {
    VkMemoryPropertyFlags    propertyFlags;
    uint32_t                 heapIndex;
} VkMemoryType;

VkMemoryType::propertyFlags可能 设置的位,表示内存类型的属性,包括:

// Provided by VK_VERSION_1_0
typedef enum VkMemoryPropertyFlagBits {
    VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT = 0x00000001,
    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT = 0x00000002,
    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT = 0x00000004,
    VK_MEMORY_PROPERTY_HOST_CACHED_BIT = 0x00000008,
    VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0x00000010,
  // Provided by VK_VERSION_1_1
    VK_MEMORY_PROPERTY_PROTECTED_BIT = 0x00000020,
  // Provided by VK_AMD_device_coherent_memory
    VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD = 0x00000040,
  // Provided by VK_AMD_device_coherent_memory
    VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD = 0x00000080,
  // Provided by VK_NV_external_memory_rdma
    VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV = 0x00000100,
} VkMemoryPropertyFlagBits;
  • VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT 位表示使用此类型分配的内存对于设备访问是最有效的。当且仅当内存类型属于设置了 VK_MEMORY_HEAP_DEVICE_LOCAL_BIT 的堆时,才会设置此属性。

  • VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT 位表示可以使用 vkMapMemory 将使用此类型分配的内存映射到主机访问。

  • VK_MEMORY_PROPERTY_HOST_COHERENT_BIT 位表示主机缓存管理命令 vkFlushMappedMemoryRangesvkInvalidateMappedMemoryRanges 不需要管理主机上的可用性和可见性

  • VK_MEMORY_PROPERTY_HOST_CACHED_BIT 位表示使用此类型分配的内存在主机上被缓存。主机访问未缓存的内存比访问缓存的内存慢,但是未缓存的内存始终与主机保持一致性。

  • VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT 位表示内存类型只允许设备访问该内存。内存类型 必须 不能同时设置 VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BITVK_MEMORY_PROPERTY_HOST_VISIBLE_BIT。此外,对象的后备内存 可能 由实现延迟提供,如延迟分配内存中所述。

  • VK_MEMORY_PROPERTY_PROTECTED_BIT 位表示内存类型只允许设备访问该内存,并且允许受保护的队列操作访问该内存。内存类型 必须 不能设置 VK_MEMORY_PROPERTY_PROTECTED_BIT,并且也不能设置 VK_MEMORY_PROPERTY_HOST_VISIBLE_BITVK_MEMORY_PROPERTY_HOST_COHERENT_BITVK_MEMORY_PROPERTY_HOST_CACHED_BIT 中的任何一个。

  • VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD 位表示设备对此内存类型的分配的访问会自动使设备上的可用性和可见性。如果与 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT 配对,则主机和设备之间也会自动执行内存域操作

  • VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD 位表示使用此类型分配的内存不会在设备上缓存。未缓存的设备内存始终与设备保持一致性。

  • VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV 位表示外部设备可以直接访问此内存。

对于任何同时设置了 VK_MEMORY_PROPERTY_HOST_COHERENT_BITVK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD 的内存,主机或设备的访问也会执行自动的内存域传输操作,这样写入总是自动对主机和设备内存域可用和可见。

设备一致性对于某些调试用例(例如,崩溃分析,其中执行单独的一致性操作可能意味着值无法正确报告)非常有用。但是,设备一致性访问可能比没有设备一致性的等效访问慢,特别是如果它们也是设备未缓存的。特别是对于设备未缓存的内存,在短时间内(例如,在帧内)重复访问相同或相邻的内存位置可能比等效的缓存内存类型慢。因此,除非确实需要,否则通常不建议使用设备一致性或设备未缓存的内存。

// Provided by VK_VERSION_1_0
typedef VkFlags VkMemoryPropertyFlags;

VkMemoryPropertyFlags 是一种位掩码类型,用于设置零个或多个 VkMemoryPropertyFlagBits 的掩码。

如果 VkPhysicalDeviceMemoryBudgetPropertiesEXT 结构包含在 VkPhysicalDeviceMemoryProperties2pNext 链中,则会填充当前的内存预算和使用情况。

VkPhysicalDeviceMemoryBudgetPropertiesEXT 结构定义如下:

// Provided by VK_EXT_memory_budget
typedef struct VkPhysicalDeviceMemoryBudgetPropertiesEXT {
    VkStructureType    sType;
    void*              pNext;
    VkDeviceSize       heapBudget[VK_MAX_MEMORY_HEAPS];
    VkDeviceSize       heapUsage[VK_MAX_MEMORY_HEAPS];
} VkPhysicalDeviceMemoryBudgetPropertiesEXT;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • heapBudget 是一个包含 VK_MAX_MEMORY_HEAPSVkDeviceSize 值的数组,其中返回内存预算,每个内存堆对应一个元素。堆的预算是对进程在分配 可能 失败或导致性能下降之前可以从该堆分配多少内存的粗略估计。预算包括任何当前已分配的设备内存。

  • heapUsage 是一个包含 VK_MAX_MEMORY_HEAPSVkDeviceSize 值的数组,其中返回内存使用情况,每个内存堆对应一个元素。堆的使用情况是对进程当前在该堆中使用的内存量的估计。

此结构中返回的值不是不变的。对于大于或等于 VkPhysicalDeviceMemoryProperties::memoryHeapCount 的数组元素,heapBudgetheapUsage必须 为零。对于小于 VkPhysicalDeviceMemoryProperties::memoryHeapCount 的数组元素,heapBudget必须 为非零值。对于每个堆,heapBudget必须 小于或等于 VkMemoryHeap::size

有效使用(隐式)
  • VUID-VkPhysicalDeviceMemoryBudgetPropertiesEXT-sType-sType
    sType 必须VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT

设备内存对象

Vulkan 设备通过 API 中由 VkDeviceMemory 句柄表示的内存对象来操作设备内存中的数据。

// Provided by VK_VERSION_1_0
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeviceMemory)

设备内存分配

要分配内存对象,请调用:

// Provided by VK_VERSION_1_0
VkResult vkAllocateMemory(
    VkDevice                                    device,
    const VkMemoryAllocateInfo*                 pAllocateInfo,
    const VkAllocationCallbacks*                pAllocator,
    VkDeviceMemory*                             pMemory);
  • device 是拥有内存的逻辑设备。

  • pAllocateInfo 是指向 VkMemoryAllocateInfo 结构的指针,该结构描述了分配的参数。成功返回的分配 必须 使用请求的参数,实现不允许进行替换。

  • pAllocator 控制主机内存分配,如内存分配章节中所述。

  • pMemory 是指向 VkDeviceMemory 句柄的指针,其中返回有关已分配内存的信息。

vkAllocateMemory 返回的分配保证满足实现的任何对齐要求。例如,如果实现要求图像的对齐为 128 字节,缓冲区的对齐为 64 字节,则通过此机制返回的设备内存将是 128 字节对齐的。这确保应用程序 可以 在同一内存对象中正确地子分配不同类型的对象(可能具有不同的对齐要求)。

分配内存时,其内容是 未定义的,但有以下约束:

  • 非保护内存的内容必须不能依赖于受保护内存对象的内容,即使这些内存对象之前已被释放。

一个应用程序分配的内存的内容应该不能依赖于另一个应用程序的受保护内存对象的数据,即使这些内存对象之前已被释放。

VkDevice 中同时存在的有效内存分配的最大数量可能会受到实现或平台相关的限制。 maxMemoryAllocationCount 特性描述了在遇到这些内部限制之前可以同时存在的分配数量。

由于历史原因,如果超出 maxMemoryAllocationCount,一些实现可能会返回 VK_ERROR_TOO_MANY_OBJECTS。超出此限制将导致未定义的行为,应用程序不应依赖于返回的错误代码来识别何时达到限制。

许多受保护内存的实现涉及复杂的硬件和系统软件支持,并且通常在同时进行的受保护内存分配(来自具有 VK_MEMORY_PROPERTY_PROTECTED_BIT 属性的内存类型)的数量上,比非受保护内存分配有额外且低得多的限制。这些限制可能是系统范围的,并且取决于 Vulkan 实现之外的多种因素,因此无法在 Vulkan 中查询。应用程序应该通过积极地进行子分配,尽可能少地使用此类内存类型的分配,并准备好即使在内存堆中明显有足够剩余容量的情况下也可能发生分配失败。作为指导,Vulkan 一致性测试套件要求在系统中没有其他受保护内存使用活动时,至少可以同时存在 80 个最小大小的分配。

某些平台可能对单个分配的最大大小有限制。例如,某些系统可能无法创建大小大于或等于 4GB 的分配。这种限制取决于实现,如果发生此类失败,则必须返回错误 VK_ERROR_OUT_OF_DEVICE_MEMORY。此限制在 VkPhysicalDeviceMaintenance3Properties::maxMemoryAllocationSize 中声明。

分配给堆的累积内存大小可能受到指定堆大小的限制。在这种情况下,分配的内存会按设备和每个堆进行跟踪。某些平台允许过度分配到其他堆中。过度分配的行为可以通过 VK_AMD_memory_overallocation_behavior 扩展来指定。

如果启用了 VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT::pageableDeviceLocalMemory 特性,则从 VkMemoryHeap::flags 中包含 VK_MEMORY_HEAP_DEVICE_LOCAL_BIT 的堆中进行的内存分配可能会被透明地移动到主机本地内存,从而允许多个应用程序共享设备本地内存。如果当进行新的分配时,设备本地内存中没有剩余空间,则其他分配可能会被透明地移出以腾出空间。操作系统将根据特定于平台的标准确定要将哪些分配移动到设备本地内存或主机本地内存。为了帮助操作系统做出好的选择,应用程序应该使用 VkMemoryPriorityAllocateInfoEXT 设置适当的内存优先级,并在必要时使用 vkSetDeviceMemoryPriorityEXT 进行调整。优先级较高的分配将首先移动到设备本地内存。

在没有 VK_MEMORY_HEAP_DEVICE_LOCAL_BIT 属性的堆上进行的内存分配,不会被操作系统透明地提升到设备本地内存。

有效用法
有效使用(隐式)
  • VUID-vkAllocateMemory-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkAllocateMemory-pAllocateInfo-parameter
    pAllocateInfo 必须是指向有效 VkMemoryAllocateInfo 结构的有效指针。

  • VUID-vkAllocateMemory-pAllocator-parameter
    如果 pAllocator 不是 NULL,则 pAllocator 必须是指向有效 VkAllocationCallbacks 结构的有效指针。

  • VUID-vkAllocateMemory-pMemory-parameter
    pMemory 必须是指向 VkDeviceMemory 句柄的有效指针。

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

  • VK_ERROR_INVALID_EXTERNAL_HANDLE

  • VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS_KHR

VkMemoryAllocateInfo 结构的定义如下:

// Provided by VK_VERSION_1_0
typedef struct VkMemoryAllocateInfo {
    VkStructureType    sType;
    const void*        pNext;
    VkDeviceSize       allocationSize;
    uint32_t           memoryTypeIndex;
} VkMemoryAllocateInfo;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • allocationSize 是分配的大小(以字节为单位)。

  • memoryTypeIndex 是一个索引,用于标识 VkPhysicalDeviceMemoryProperties 结构的 memoryTypes 数组中的内存类型。

已分配的设备内存对象的内部数据必须包含对实现特定资源的引用,称为内存对象的有效负载。应用程序可以导入和导出该内部数据到设备内存对象以及从设备内存对象中导出,以在 Vulkan 实例和其他兼容 API 之间共享数据。如果 VkMemoryAllocateInfo 结构的 pNext 链包含以下结构之一,则它定义了一个内存导入操作:

如果参数定义了一个导入操作,并且外部句柄类型为 VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BITVK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BITVK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT,则 allocationSize 将被忽略。实现 必须 从操作系统查询这些分配的大小。

通过内存导入操作构造的设备内存对象是否持有对其有效负载的引用,取决于用于执行导入的句柄类型的属性,如下面为每个有效的句柄类型定义的那样。导入内存 必须 不修改内存的内容。实现 必须 确保导入内存不会使导入的 Vulkan 实例访问其他 Vulkan 实例中的任何内存或资源,除了与导入的内存对象对应的内存或资源。实现 必须 还确保访问未初始化的导入内存不会使导入的 Vulkan 实例从导出的 Vulkan 实例获取数据,反之亦然。

导出和导入的内存如何隔离取决于实现,但应用程序应注意,这种隔离 可能 会阻止实现将多个可导出的内存对象放置在同一物理或虚拟页面中。因此,应用程序 应该 尽可能避免创建许多小的外部内存对象。

导入内存 必须 不会增加系统内的总体堆使用量。但是,它 必须 影响以下每个进程的值:

执行内存导入操作时,应用程序有责任确保外部句柄及其关联的有效负载满足所有有效的用法要求。但是,实现 必须 对外部句柄和有效负载执行充分的验证,以确保该操作产生有效的内存对象,该对象在按照其分配参数允许使用时不会导致程序终止、设备丢失、队列停顿或损坏其他资源。如果提供的外部句柄不满足这些要求,则实现 必须 使内存导入操作失败,并返回错误代码 VK_ERROR_INVALID_EXTERNAL_HANDLE。如果参数定义了一个导出操作,并且外部句柄类型为 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,则实现 应该 不严格遵循 memoryTypeIndex。相反,它们 应该 在内部修改分配,以使用应用程序给定用法所需的内存类型。这是因为对于导出操作,应用程序目前无法在分配之前知道内存类型索引。

有效用法
  • VUID-VkMemoryAllocateInfo-allocationSize-07897
    如果参数没有定义导入或导出操作,则 allocationSize 必须 大于 0

  • VUID-VkMemoryAllocateInfo-None-06657
    参数 必须 不定义多个导入操作

  • VUID-VkMemoryAllocateInfo-allocationSize-07899
    如果参数定义了一个导出操作,并且句柄类型不是 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,则 allocationSize 必须 大于 0

  • VUID-VkMemoryAllocateInfo-buffer-06380
    如果参数定义了从 VkBufferCollectionFUCHSIA 的导入操作,并且 VkMemoryDedicatedAllocateInfo::buffer 存在且非 NULL,则 VkImportMemoryBufferCollectionFUCHSIA::collectionVkImportMemoryBufferCollectionFUCHSIA::index 必须 分别与 VkBufferCollectionBufferCreateInfoFUCHSIA::collectionVkBufferCollectionBufferCreateInfoFUCHSIA::index 相匹配,其中 VkBufferCollectionBufferCreateInfoFUCHSIA 结构用于创建 VkMemoryDedicatedAllocateInfo::buffer

  • VUID-VkMemoryAllocateInfo-image-06381
    如果参数定义了从 VkBufferCollectionFUCHSIA 的导入操作,并且 VkMemoryDedicatedAllocateInfo::image 存在且非 NULL,则 VkImportMemoryBufferCollectionFUCHSIA::collectionVkImportMemoryBufferCollectionFUCHSIA::index 必须 分别与 VkBufferCollectionImageCreateInfoFUCHSIA::collectionVkBufferCollectionImageCreateInfoFUCHSIA::index 相匹配,其中 VkBufferCollectionImageCreateInfoFUCHSIA 结构用于创建 VkMemoryDedicatedAllocateInfo::image

  • VUID-VkMemoryAllocateInfo-allocationSize-06382
    如果参数定义了从 VkBufferCollectionFUCHSIA 的导入操作,则 allocationSize 必须 与通过 vkGetImageMemoryRequirementsvkGetBufferMemoryRequirements 分别为基于图像或基于缓冲区的集合检索的 VkMemoryRequirements::size 值相匹配。

  • VUID-VkMemoryAllocateInfo-pNext-06383
    如果参数定义了从 VkBufferCollectionFUCHSIA 的导入操作,则 pNext必须 包含一个 VkMemoryDedicatedAllocateInfo 结构,其 imagebuffer 字段设置为除 VK_NULL_HANDLE 之外的值。

  • VUID-VkMemoryAllocateInfo-image-06384
    如果参数定义了从 VkBufferCollectionFUCHSIA 的导入操作,并且 VkMemoryDedicatedAllocateInfo::image 不是 VK_NULL_HANDLE,则 image 必须 使用链接到其 VkImageCreateInfo::pNext 指针的 VkBufferCollectionImageCreateInfoFUCHSIA 结构创建。

  • VUID-VkMemoryAllocateInfo-buffer-06385
    如果参数定义了从 VkBufferCollectionFUCHSIA 导入的操作,并且 VkMemoryDedicatedAllocateInfo::buffer 不是 VK_NULL_HANDLE,则 buffer 必须使用链接到其 VkBufferCreateInfo::pNext 指针的 VkBufferCollectionBufferCreateInfoFUCHSIA 结构体创建。

  • VUID-VkMemoryAllocateInfo-memoryTypeIndex-06386
    如果参数定义了从 VkBufferCollectionFUCHSIA 导入的操作,则 memoryTypeIndex 必须来自 VkBufferCollectionPropertiesFUCHSIA,该结构体通过 vkGetBufferCollectionPropertiesFUCHSIA 获取。

  • VUID-VkMemoryAllocateInfo-pNext-00639
    如果 pNext 链包含 VkExportMemoryAllocateInfo 结构体,并且在 VkExportMemoryAllocateInfo::handleTypes 中指定的任何句柄类型都需要专用分配,正如 vkGetPhysicalDeviceImageFormatProperties2VkExternalImageFormatProperties::externalMemoryProperties.externalMemoryFeatures 中报告的,或者 vkGetPhysicalDeviceExternalBufferPropertiesVkExternalBufferProperties::externalMemoryProperties.externalMemoryFeatures 中报告的那样,则 pNext必须包含一个 VkMemoryDedicatedAllocateInfoVkDedicatedAllocationMemoryAllocateInfoNV 结构体,且其 imagebuffer 成员的值必须设置为非 VK_NULL_HANDLE 的值。

  • VUID-VkMemoryAllocateInfo-pNext-00640
    如果 pNext 链包含 VkExportMemoryAllocateInfo 结构体,则它必须不包含 VkExportMemoryAllocateInfoNVVkExportMemoryWin32HandleInfoNV 结构体。

  • VUID-VkMemoryAllocateInfo-pNext-00641
    如果 pNext 链包含 VkImportMemoryWin32HandleInfoKHR 结构体,则它必须不包含 VkImportMemoryWin32HandleInfoNV 结构体。

  • VUID-VkMemoryAllocateInfo-allocationSize-01742
    如果参数定义了导入操作,指定的外部句柄由 Vulkan API 创建,并且外部句柄类型为 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,则 allocationSizememoryTypeIndex 的值必须与创建要导入的有效负载时指定的值相匹配。

  • VUID-VkMemoryAllocateInfo-None-00643
    如果参数定义了导入操作,并且指定的外部句柄由 Vulkan API 创建,则由 VkMemoryAllocateFlagsInfo 指定的设备掩码必须与分配要导入的有效负载时指定的掩码相匹配。

  • VUID-VkMemoryAllocateInfo-None-00644
    如果参数定义了导入操作,并且指定的外部句柄由 Vulkan API 创建,则传递给 vkAllocateMemory 的逻辑设备所包含的物理设备列表必须与最初分配有效负载的逻辑设备所包含的物理设备列表相匹配。

  • VUID-VkMemoryAllocateInfo-memoryTypeIndex-00645
    如果参数定义了导入操作,并且外部句柄是 NT 句柄或在 Vulkan API 之外创建的全局共享句柄,则 memoryTypeIndex 的值必须vkGetMemoryWin32HandlePropertiesKHR 返回的值之一。

  • VUID-VkMemoryAllocateInfo-allocationSize-01743
    如果参数定义了导入操作,指定的外部句柄由 Vulkan API 创建,并且外部句柄类型为 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BITVK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,则 allocationSizememoryTypeIndex 的值必须与创建要导入的有效负载时指定的值相匹配。

  • VUID-VkMemoryAllocateInfo-allocationSize-00647
    如果参数定义了导入操作,并且外部句柄类型为 VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT,则 allocationSize 必须与创建从中提取有效负载的 Direct3D 12 堆时指定的大小相匹配。

  • VUID-VkMemoryAllocateInfo-memoryTypeIndex-00648
    如果参数定义了导入操作,并且外部句柄是在 Vulkan API 之外创建的 POSIX 文件描述符,则 memoryTypeIndex 的值必须vkGetMemoryFdPropertiesKHR 返回的值之一。

  • VUID-VkMemoryAllocateInfo-memoryTypeIndex-01872
    如果未启用 protectedMemory 功能,则 VkMemoryAllocateInfo::memoryTypeIndex 必须不指示报告 VK_MEMORY_PROPERTY_PROTECTED_BIT 的内存类型。

  • VUID-VkMemoryAllocateInfo-memoryTypeIndex-01744
    如果参数定义了导入操作,并且外部句柄是主机指针,则 memoryTypeIndex 的值必须vkGetMemoryHostPointerPropertiesEXT 返回的值之一。

  • VUID-VkMemoryAllocateInfo-allocationSize-01745
    如果参数定义了导入操作,并且外部句柄是主机指针,则 allocationSize 必须VkPhysicalDeviceExternalMemoryHostPropertiesEXT::minImportedHostPointerAlignment 的整数倍。

  • VUID-VkMemoryAllocateInfo-pNext-02805
    如果参数定义了导入操作,并且外部句柄是主机指针,则 pNext必须不包含 imagebuffer 字段设置为非 VK_NULL_HANDLE 的值的 VkDedicatedAllocationMemoryAllocateInfoNV 结构体。

  • VUID-VkMemoryAllocateInfo-pNext-02806
    如果参数定义了一个导入操作,并且外部句柄是一个主机指针,则 pNext必须 不包含一个 VkMemoryDedicatedAllocateInfo 结构体,且该结构体的 imagebuffer 字段设置为除 VK_NULL_HANDLE 以外的值。

  • VUID-VkMemoryAllocateInfo-allocationSize-02383
    如果参数定义了一个导入操作,并且外部句柄类型是 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,则 allocationSize 必须vkGetAndroidHardwareBufferPropertiesANDROID 为 Android 硬件缓冲区返回的大小。

  • VUID-VkMemoryAllocateInfo-pNext-02384
    如果参数定义了一个导入操作,并且外部句柄类型是 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,且 pNext 链不包含 VkMemoryDedicatedAllocateInfo 结构体或 VkMemoryDedicatedAllocateInfo::imageVK_NULL_HANDLE,则 Android 硬件缓冲区的 AHardwareBuffer_Desc::format 必须AHARDWAREBUFFER_FORMAT_BLOB,且 AHardwareBuffer_Desc::usage 必须包含 AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER

  • VUID-VkMemoryAllocateInfo-memoryTypeIndex-02385
    如果参数定义了一个导入操作,并且外部句柄类型是 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,则 memoryTypeIndex 必须vkGetAndroidHardwareBufferPropertiesANDROID 为 Android 硬件缓冲区返回的其中一个值。

  • VUID-VkMemoryAllocateInfo-pNext-01874
    如果参数没有定义导入操作,并且 pNext 链包含一个 VkExportMemoryAllocateInfo 结构体,其 handleTypes 成员中包含 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,并且 pNext 链包含一个 VkMemoryDedicatedAllocateInfo 结构体,其 image 不等于 VK_NULL_HANDLE,那么 allocationSize 必须0

  • VUID-VkMemoryAllocateInfo-pNext-07900
    如果参数定义了一个导出操作,句柄类型是 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,并且 pNext 不包含 VkMemoryDedicatedAllocateInfo 结构体,则 allocationSize 必须 大于 0

  • VUID-VkMemoryAllocateInfo-pNext-07901
    如果参数定义了一个导出操作,句柄类型是 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,并且 pNext 链包含一个 VkMemoryDedicatedAllocateInfo 结构体,其 buffer 设置为一个有效的 VkBuffer 对象,则 allocationSize 必须 大于 0

  • VUID-VkMemoryAllocateInfo-pNext-02386
    如果参数定义了一个导入操作,外部句柄是一个 Android 硬件缓冲区,并且 pNext 链包含一个 VkMemoryDedicatedAllocateInfo,其 image 不为 VK_NULL_HANDLE,则 Android 硬件缓冲区的 AHardwareBuffer::usage 必须 至少包含 AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFERAHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGEAHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER 中的一个。

  • VUID-VkMemoryAllocateInfo-pNext-02387
    如果参数定义了一个导入操作,外部句柄是一个 Android 硬件缓冲区,并且 pNext 链包含一个 VkMemoryDedicatedAllocateInfo,其 image 不为 VK_NULL_HANDLE,则 image 的格式 必须VK_FORMAT_UNDEFINEDvkGetAndroidHardwareBufferPropertiesANDROIDVkAndroidHardwareBufferFormatPropertiesANDROID::format 中为 Android 硬件缓冲区返回的格式。

  • VUID-VkMemoryAllocateInfo-pNext-02388
    如果参数定义了一个导入操作,外部句柄是一个 Android 硬件缓冲区,并且 pNext 链包含一个 VkMemoryDedicatedAllocateInfo 结构体,其 image 不为 VK_NULL_HANDLE,则 image 的宽度、高度和数组层维度与 Android 硬件缓冲区的 AHardwareBuffer_Desc 必须 相同。

  • VUID-VkMemoryAllocateInfo-pNext-02389
    如果参数定义了一个导入操作,外部句柄是一个 Android 硬件缓冲区,并且 pNext 链包含一个 VkMemoryDedicatedAllocateInfo 结构体,其 image 不为 VK_NULL_HANDLE,且 Android 硬件缓冲区的 AHardwareBuffer::usage 包含 AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE,则 image 必须 具有完整的 mipmap 链。

  • VUID-VkMemoryAllocateInfo-pNext-02586
    如果参数定义了一个导入操作,外部句柄是一个 Android 硬件缓冲区,并且 pNext 链包含一个 VkMemoryDedicatedAllocateInfo 结构体,其 image 不为 VK_NULL_HANDLE,且 Android 硬件缓冲区的 AHardwareBuffer::usage 不包含 AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE,则 image 必须 只有一个 mipmap 层级。

  • VUID-VkMemoryAllocateInfo-pNext-02390
    如果参数定义了一个导入操作,外部句柄是一个 Android 硬件缓冲区,并且 pNext 链包含一个 VkMemoryDedicatedAllocateInfo 结构体,其 image 不为 VK_NULL_HANDLE,则 image 的使用中设置的每个位 必须 列在 AHardwareBuffer Usage Equivalence 中,如果列出了对应的 AHARDWAREBUFFER_USAGE 位,则该位 必须 包含在 Android 硬件缓冲区的 AHardwareBuffer_Desc::usage 中。

  • VUID-VkMemoryAllocateInfo-screenBufferImport-08941
    如果参数定义了一个导入操作,并且外部句柄类型是 VK_EXTERNAL_MEMORY_HANDLE_TYPE_SCREEN_BUFFER_BIT_QNX,则 VkPhysicalDeviceExternalMemoryScreenBufferFeaturesQNX::screenBufferImport 必须 被启用。

  • VUID-VkMemoryAllocateInfo-allocationSize-08942
    如果参数定义了一个导入操作,并且外部句柄类型是 VK_EXTERNAL_MEMORY_HANDLE_TYPE_SCREEN_BUFFER_BIT_QNX,则 allocationSize 必须vkGetScreenBufferPropertiesQNX 为 QNX Screen 缓冲区返回的大小。

  • VUID-VkMemoryAllocateInfo-memoryTypeIndex-08943
    如果参数定义了一个导入操作,并且外部句柄类型是 VK_EXTERNAL_MEMORY_HANDLE_TYPE_SCREEN_BUFFER_BIT_QNX,则 memoryTypeIndex 必须vkGetScreenBufferPropertiesQNX 为 QNX Screen 缓冲区返回的其中一个值。

  • VUID-VkMemoryAllocateInfo-pNext-08944
    如果参数定义了一个导入操作,外部句柄是 QNX Screen 缓冲区,并且 pNext 链包含一个 VkMemoryDedicatedAllocateInfo,其 image 不是 VK_NULL_HANDLE,则 QNX Screen 的缓冲区必须是一个有效的 QNX Screen 缓冲区

  • VUID-VkMemoryAllocateInfo-pNext-08945
    如果参数定义了一个导入操作,外部句柄是 QNX Screen 缓冲区,并且 pNext 链包含一个 VkMemoryDedicatedAllocateInfo,其 image 不是 VK_NULL_HANDLE,则 image 的格式必须VK_FORMAT_UNDEFINED,或者是 vkGetScreenBufferPropertiesQNXVkScreenBufferFormatPropertiesQNX::format 中为 QNX Screen 缓冲区返回的格式

  • VUID-VkMemoryAllocateInfo-pNext-08946
    如果参数定义了一个导入操作,外部句柄是 QNX Screen 缓冲区,并且 pNext 链包含一个 VkMemoryDedicatedAllocateInfo 结构,其 image 不是 VK_NULL_HANDLE,则 image 的宽度、高度和数组层维度与 QNX Screen 缓冲区的 _screen_buffer必须相同

  • VUID-VkMemoryAllocateInfo-opaqueCaptureAddress-03329
    如果 VkMemoryOpaqueCaptureAddressAllocateInfo::opaqueCaptureAddress 不为零,则 VkMemoryAllocateFlagsInfo::flags必须包含 VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT

  • VUID-VkMemoryAllocateInfo-flags-03330
    如果 VkMemoryAllocateFlagsInfo::flags 包含 VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT,则 bufferDeviceAddressCaptureReplay 特性必须启用

  • VUID-VkMemoryAllocateInfo-flags-03331
    如果 VkMemoryAllocateFlagsInfo::flags 包含 VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,则 bufferDeviceAddress 特性必须启用

  • VUID-VkMemoryAllocateInfo-pNext-03332
    如果 pNext 链包含 VkImportMemoryHostPointerInfoEXT 结构,则 VkMemoryOpaqueCaptureAddressAllocateInfo::opaqueCaptureAddress必须为零

  • VUID-VkMemoryAllocateInfo-opaqueCaptureAddress-03333
    如果参数定义了一个导入操作,则 VkMemoryOpaqueCaptureAddressAllocateInfo::opaqueCaptureAddress必须为零

  • VUID-VkMemoryAllocateInfo-None-04749
    如果参数定义了一个导入操作,且外部句柄类型为 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA,则 memoryTypeIndex 的值必须是一个索引,该索引标识由对 vkGetMemoryZirconHandlePropertiesFUCHSIA 的调用填充的 VkMemoryZirconHandlePropertiesFUCHSIA 结构的 memoryTypeBits 字段中的内存类型

  • VUID-VkMemoryAllocateInfo-allocationSize-07902
    如果参数定义了一个导入操作,且外部句柄类型为 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA,则 allocationSize 的值必须大于 0

  • VUID-VkMemoryAllocateInfo-allocationSize-07903
    如果参数定义了一个导入操作,且外部句柄类型为 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA,则 allocationSize 的值必须小于或等于由 zx_vmo_get_size(handle) 确定的 VMO 的大小,其中 handle 是导入的外部内存的 VMO 句柄

  • VUID-VkMemoryAllocateInfo-pNext-06780
    如果 pNext 链包含 VkExportMetalObjectCreateInfoEXT 结构,则其 exportObjectType 成员必须VK_EXPORT_METAL_OBJECT_TYPE_METAL_BUFFER_BIT_EXT

有效使用(隐式)

如果 pNext 链包含 VkMemoryDedicatedAllocateInfo 结构,则该结构包含内存可以绑定到的唯一缓冲区或图像资源的句柄。

VkMemoryDedicatedAllocateInfo 结构的定义如下

// Provided by VK_VERSION_1_1
typedef struct VkMemoryDedicatedAllocateInfo {
    VkStructureType    sType;
    const void*        pNext;
    VkImage            image;
    VkBuffer           buffer;
} VkMemoryDedicatedAllocateInfo;

或等效的

// Provided by VK_KHR_dedicated_allocation
typedef VkMemoryDedicatedAllocateInfo VkMemoryDedicatedAllocateInfoKHR;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • imageVK_NULL_HANDLE 或此内存将绑定到的图像的句柄。

  • bufferVK_NULL_HANDLE 或此内存将绑定到的缓冲区的句柄。

有效用法
  • VUID-VkMemoryDedicatedAllocateInfo-image-01432
    imagebuffer 中至少有一个 必须VK_NULL_HANDLE

  • VUID-VkMemoryDedicatedAllocateInfo-image-02964
    如果 image 不为 VK_NULL_HANDLE 且该内存不是导入的 Android 硬件缓冲区或导入的 QNX 屏幕缓冲区,则 VkMemoryAllocateInfo::allocationSize 必须 等于该图像的 VkMemoryRequirements::size

  • VUID-VkMemoryDedicatedAllocateInfo-image-01434
    如果 image 不为 VK_NULL_HANDLE,则 imageVkImageCreateInfo::flags 中创建时 必须 未设置 VK_IMAGE_CREATE_SPARSE_BINDING_BIT

  • VUID-VkMemoryDedicatedAllocateInfo-buffer-02965
    如果 buffer 不为 VK_NULL_HANDLE 且该内存不是导入的 Android 硬件缓冲区或导入的 QNX 屏幕缓冲区,则 VkMemoryAllocateInfo::allocationSize 必须 等于该缓冲区的 VkMemoryRequirements::size

  • VUID-VkMemoryDedicatedAllocateInfo-buffer-01436
    如果 buffer 不为 VK_NULL_HANDLE,则 bufferVkBufferCreateInfo::flags 中创建时 必须 未设置 VK_BUFFER_CREATE_SPARSE_BINDING_BIT

  • VUID-VkMemoryDedicatedAllocateInfo-image-01876
    如果 image 不为 VK_NULL_HANDLEVkMemoryAllocateInfo 定义了使用句柄类型 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BITVK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BITVK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BITVK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BITVK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BITVK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT 的内存导入操作,且该外部句柄是由 Vulkan API 创建的,则被导入的内存 必须 也是专用的图像分配,且 image 必须 与导入内存关联的图像相同

  • VUID-VkMemoryDedicatedAllocateInfo-buffer-01877
    如果 buffer 不为 VK_NULL_HANDLEVkMemoryAllocateInfo 定义了使用句柄类型 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BITVK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BITVK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BITVK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BITVK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BITVK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT 的内存导入操作,且该外部句柄是由 Vulkan API 创建的,则被导入的内存 必须 也是专用的缓冲区分配,且 buffer 必须 与导入内存关联的缓冲区相同

  • VUID-VkMemoryDedicatedAllocateInfo-image-01878
    如果 image 不为 VK_NULL_HANDLEVkMemoryAllocateInfo 定义了使用句柄类型 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT 的内存导入操作,则被导入的内存 必须 也是专用的图像分配,且 image 必须 与导入内存关联的图像相同

  • VUID-VkMemoryDedicatedAllocateInfo-buffer-01879
    如果 buffer 不为 VK_NULL_HANDLEVkMemoryAllocateInfo 定义了使用句柄类型 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT 的内存导入操作,则被导入的内存 必须 也是专用的缓冲区分配,且 buffer 必须 与导入内存关联的缓冲区相同

  • VUID-VkMemoryDedicatedAllocateInfo-image-01797
    如果 image 不为 VK_NULL_HANDLE,则 imageVkImageCreateInfo::flags 中创建时 必须 未设置 VK_IMAGE_CREATE_DISJOINT_BIT

  • VUID-VkMemoryDedicatedAllocateInfo-image-04751
    如果 image 不为 VK_NULL_HANDLEVkMemoryAllocateInfo 定义了使用句柄类型 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA 的内存导入操作,则被导入的内存 必须 也是专用的图像分配,且 image 必须 与导入内存关联的图像相同

  • VUID-VkMemoryDedicatedAllocateInfo-buffer-04752
    如果 buffer 不为 VK_NULL_HANDLEVkMemoryAllocateInfo 定义了使用句柄类型 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA 的内存导入操作,则被导入的内存 必须 也是专用的缓冲区分配,且 buffer 必须 与导入内存关联的缓冲区相同

有效使用(隐式)
  • VUID-VkMemoryDedicatedAllocateInfo-sType-sType
    sType 必须VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO

  • VUID-VkMemoryDedicatedAllocateInfo-image-parameter
    如果 image 不为 VK_NULL_HANDLE,则 image 必须 是一个有效的 VkImage 句柄

  • VUID-VkMemoryDedicatedAllocateInfo-buffer-parameter
    如果 buffer 不为 VK_NULL_HANDLE,则 buffer 必须 是一个有效的 VkBuffer 句柄

  • VUID-VkMemoryDedicatedAllocateInfo-commonparent
    bufferimage 这两个非忽略参数的有效句柄 必须 从同一个 VkDevice 创建、分配或检索

如果 pNext 链包含 VkDedicatedAllocationMemoryAllocateInfoNV 结构,则该结构包含唯一缓冲区或图像资源的句柄,该内存 可以 绑定到该资源。

VkDedicatedAllocationMemoryAllocateInfoNV 结构定义如下

// Provided by VK_NV_dedicated_allocation
typedef struct VkDedicatedAllocationMemoryAllocateInfoNV {
    VkStructureType    sType;
    const void*        pNext;
    VkImage            image;
    VkBuffer           buffer;
} VkDedicatedAllocationMemoryAllocateInfoNV;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • imageVK_NULL_HANDLE 或此内存将绑定到的图像的句柄。

  • bufferVK_NULL_HANDLE 或此内存将绑定到的缓冲区的句柄。

有效用法
  • VUID-VkDedicatedAllocationMemoryAllocateInfoNV-image-00649
    imagebuffer 中至少有一个 必须VK_NULL_HANDLE

  • VUID-VkDedicatedAllocationMemoryAllocateInfoNV-image-00650
    如果 image 不是 VK_NULL_HANDLE,则该图像必须已使用 VkDedicatedAllocationImageCreateInfoNV::dedicatedAllocation 等于 VK_TRUE 创建。

  • VUID-VkDedicatedAllocationMemoryAllocateInfoNV-buffer-00651
    如果 buffer 不是 VK_NULL_HANDLE,则该缓冲区必须已使用 VkDedicatedAllocationBufferCreateInfoNV::dedicatedAllocation 等于 VK_TRUE 创建。

  • VUID-VkDedicatedAllocationMemoryAllocateInfoNV-image-00652
    如果 image 不是 VK_NULL_HANDLE,则 VkMemoryAllocateInfo::allocationSize 必须等于该图像的 VkMemoryRequirements::size

  • VUID-VkDedicatedAllocationMemoryAllocateInfoNV-buffer-00653
    如果 buffer 不是 VK_NULL_HANDLE,则 VkMemoryAllocateInfo::allocationSize 必须等于该缓冲区的 VkMemoryRequirements::size

  • VUID-VkDedicatedAllocationMemoryAllocateInfoNV-image-00654
    如果 image 不是 VK_NULL_HANDLE 并且 VkMemoryAllocateInfo 定义了一个内存导入操作,则导入的内存必须也是一个专用的图像分配,并且 image 必须与导入内存关联的图像相同。

  • VUID-VkDedicatedAllocationMemoryAllocateInfoNV-buffer-00655
    如果 buffer 不是 VK_NULL_HANDLE 并且 VkMemoryAllocateInfo 定义了一个内存导入操作,则导入的内存必须也是一个专用的缓冲区分配,并且 buffer 必须与导入内存关联的缓冲区相同。

有效使用(隐式)
  • VUID-VkDedicatedAllocationMemoryAllocateInfoNV-sType-sType
    sType 必须VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV

  • VUID-VkDedicatedAllocationMemoryAllocateInfoNV-image-parameter
    如果 image 不为 VK_NULL_HANDLE,则 image 必须 是一个有效的 VkImage 句柄

  • VUID-VkDedicatedAllocationMemoryAllocateInfoNV-buffer-parameter
    如果 buffer 不为 VK_NULL_HANDLE,则 buffer 必须 是一个有效的 VkBuffer 句柄

  • VUID-VkDedicatedAllocationMemoryAllocateInfoNV-commonparent
    bufferimage 这两个非忽略参数的有效句柄 必须 从同一个 VkDevice 创建、分配或检索

如果 pNext 链包含一个 VkMemoryPriorityAllocateInfoEXT 结构,则该结构包含内存的优先级。

VkMemoryPriorityAllocateInfoEXT 结构定义如下:

// Provided by VK_EXT_memory_priority
typedef struct VkMemoryPriorityAllocateInfoEXT {
    VkStructureType    sType;
    const void*        pNext;
    float              priority;
} VkMemoryPriorityAllocateInfoEXT;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • priority 是一个介于 01 之间的浮点值,表示分配相对于其他内存分配的优先级。值越大,优先级越高。优先级的粒度取决于实现。

当系统内存不足时,具有较高优先级的内存分配可能更可能保留在设备本地内存中。

如果未包含此结构,则相当于 priority 值为 0.5

有效用法
  • VUID-VkMemoryPriorityAllocateInfoEXT-priority-02602
    priority 必须介于 01 之间,包括 01

有效使用(隐式)
  • VUID-VkMemoryPriorityAllocateInfoEXT-sType-sType
    sType 必须VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT

要修改现有内存分配的优先级,请调用

// Provided by VK_EXT_pageable_device_local_memory
void vkSetDeviceMemoryPriorityEXT(
    VkDevice                                    device,
    VkDeviceMemory                              memory,
    float                                       priority);
  • device 是拥有内存的逻辑设备。

  • memory 是将应用新优先级的 VkDeviceMemory 对象。

  • priority 是一个介于 01 之间的浮点值,表示分配相对于其他内存分配的优先级。值越大,优先级越高。优先级的粒度取决于实现。

当系统内存不足时,具有较高优先级的内存分配可能更可能保留在设备本地内存中。

有效用法
  • VUID-vkSetDeviceMemoryPriorityEXT-priority-06258
    priority 必须介于 01 之间,包括 01

有效使用(隐式)
  • VUID-vkSetDeviceMemoryPriorityEXT-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkSetDeviceMemoryPriorityEXT-memory-parameter
    memory 必须是一个有效的 VkDeviceMemory 句柄。

  • VUID-vkSetDeviceMemoryPriorityEXT-memory-parent
    memory 必须已从 device 创建、分配或检索。

当分配其有效负载可能导出到另一个进程或 Vulkan 实例的内存时,请将一个 VkExportMemoryAllocateInfo 结构添加到 VkMemoryAllocateInfo 结构的 pNext 链中,指定可能导出的句柄类型。

VkExportMemoryAllocateInfo 结构定义如下:

// Provided by VK_VERSION_1_1
typedef struct VkExportMemoryAllocateInfo {
    VkStructureType                    sType;
    const void*                        pNext;
    VkExternalMemoryHandleTypeFlags    handleTypes;
} VkExportMemoryAllocateInfo;

或等效的

// Provided by VK_KHR_external_memory
typedef VkExportMemoryAllocateInfo VkExportMemoryAllocateInfoKHR;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • handleTypes 是零或 VkExternalMemoryHandleTypeFlagBits 的位掩码,指定应用程序可以从生成的分配中导出的一个或多个内存句柄类型。应用程序可以为同一分配请求多个句柄类型。

有效用法
有效使用(隐式)
  • VUID-VkExportMemoryAllocateInfo-sType-sType
    sType 必须VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO

  • VUID-VkExportMemoryAllocateInfo-handleTypes-parameter
    handleTypes 必须VkExternalMemoryHandleTypeFlagBits 值的有效组合。

当分配可能导出到另一个进程或 Vulkan 实例的内存时,请将一个 VkExportMemoryAllocateInfoNV 结构添加到 VkMemoryAllocateInfo 结构的 pNext 链中,指定可能导出的句柄类型。

VkExportMemoryAllocateInfoNV 结构定义如下:

// Provided by VK_NV_external_memory
typedef struct VkExportMemoryAllocateInfoNV {
    VkStructureType                      sType;
    const void*                          pNext;
    VkExternalMemoryHandleTypeFlagsNV    handleTypes;
} VkExportMemoryAllocateInfoNV;
有效使用(隐式)
  • VUID-VkExportMemoryAllocateInfoNV-sType-sType
    sType 必须VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV

  • VUID-VkExportMemoryAllocateInfoNV-handleTypes-parameter
    handleTypes 必须VkExternalMemoryHandleTypeFlagBitsNV 值的有效组合

Win32 外部内存

要指定从内存对象导出的 NT 句柄的附加属性,请将 VkExportMemoryWin32HandleInfoKHR 结构添加到 VkMemoryAllocateInfo 结构的 pNext 链中。VkExportMemoryWin32HandleInfoKHR 结构的定义如下:

// Provided by VK_KHR_external_memory_win32
typedef struct VkExportMemoryWin32HandleInfoKHR {
    VkStructureType               sType;
    const void*                   pNext;
    const SECURITY_ATTRIBUTES*    pAttributes;
    DWORD                         dwAccess;
    LPCWSTR                       name;
} VkExportMemoryWin32HandleInfoKHR;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • pAttributes 是指向 Windows SECURITY_ATTRIBUTES 结构的指针,该结构指定句柄的安全属性。

  • dwAccess 是一个 DWORD,指定句柄的访问权限。

  • name 是一个以 null 结尾的 UTF-16 字符串,用于关联从创建的内存导出的 NT 句柄引用的负载。

如果 VkExportMemoryAllocateInfo 未包含在同一个 pNext 链中,则忽略此结构。

如果 VkExportMemoryAllocateInfo 包含在 VkMemoryAllocateInfopNext 链中,且使用 Windows handleType,但 VkExportMemoryWin32HandleInfoKHR 未包含在 pNext 链中,或者已包含但 pAttributes 设置为 NULL,则将使用默认安全描述符值,并且应用程序创建的子进程将不会继承该句柄,如 MSDN 文档“同步对象安全性和访问权限”1 中所述。此外,如果该结构不存在,则使用的访问权限取决于句柄类型。

对于以下类型的句柄:

  • VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT

实现必须确保访问权限允许对内存进行读取和写入访问。

有效用法
  • VUID-VkExportMemoryWin32HandleInfoKHR-handleTypes-00657
    如果 VkExportMemoryAllocateInfo::handleTypes 不包含 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT,则 VkMemoryAllocateInfopNext 链中必须不包含 VkExportMemoryWin32HandleInfoKHR 结构

有效使用(隐式)
  • VUID-VkExportMemoryWin32HandleInfoKHR-sType-sType
    sType 必须VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR

  • VUID-VkExportMemoryWin32HandleInfoKHR-pAttributes-parameter
    如果 pAttributes 不为 NULL,则 pAttributes 必须是指向有效 SECURITY_ATTRIBUTES 值的有效指针

要从 Windows 句柄导入内存,请将 VkImportMemoryWin32HandleInfoKHR 结构添加到 VkMemoryAllocateInfo 结构的 pNext 链中。

VkImportMemoryWin32HandleInfoKHR 结构的定义如下:

// Provided by VK_KHR_external_memory_win32
typedef struct VkImportMemoryWin32HandleInfoKHR {
    VkStructureType                       sType;
    const void*                           pNext;
    VkExternalMemoryHandleTypeFlagBits    handleType;
    HANDLE                                handle;
    LPCWSTR                               name;
} VkImportMemoryWin32HandleInfoKHR;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • handleType 是一个 VkExternalMemoryHandleTypeFlagBits 值,指定 handlename 的类型。

  • handleNULL 或要导入的外部句柄。

  • nameNULL 或一个以 null 结尾的 UTF-16 字符串,用于命名要导入的负载。

从 Windows 句柄导入内存对象负载不会将句柄的所有权转移给 Vulkan 实现。对于定义为 NT 句柄的句柄类型,当不再需要句柄时,应用程序必须使用 CloseHandle 系统调用释放句柄所有权。对于定义为 NT 句柄的句柄类型,导入的内存对象会保持对其负载的引用。

非 NT 句柄导入操作不会向其关联的负载添加引用。如果拥有负载的原始对象被销毁,则共享该负载的所有资源和句柄将变为无效。

应用程序可以将相同的负载导入到 Vulkan 的多个实例中,导入到导出该负载的同一实例中,以及多次导入到给定的 Vulkan 实例中。在所有情况下,每个导入操作必须创建一个不同的 VkDeviceMemory 对象。

有效用法
  • VUID-VkImportMemoryWin32HandleInfoKHR-handleType-00658
    如果 handleType 不为 0,则它必须支持导入,如 VkExternalImageFormatPropertiesVkExternalBufferProperties 报告的那样

  • VUID-VkImportMemoryWin32HandleInfoKHR-handle-00659
    从中导出 handle 的内存,或者由 name 命名的内存必须在与 device 相同的底层物理设备上创建

  • VUID-VkImportMemoryWin32HandleInfoKHR-handleType-00660
    如果 handleType 不为 0,则它必须定义为 NT 句柄或全局共享句柄

  • VUID-VkImportMemoryWin32HandleInfoKHR-handleType-01439
    如果 handleType 不是 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BITVK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BITVK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BITVK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT,则 name 必须NULL

  • VUID-VkImportMemoryWin32HandleInfoKHR-handleType-01440
    如果 handleType 不为 0handleNULL,则 name 必须命名由 handleType 指定类型的有效内存资源

  • VUID-VkImportMemoryWin32HandleInfoKHR-handleType-00661
    如果 handleType 不为 0nameNULL,则 handle 必须handleType 指定类型的有效句柄

  • VUID-VkImportMemoryWin32HandleInfoKHR-handle-01441
    如果 handle 不为 NULL,则 name 必须NULL

  • VUID-VkImportMemoryWin32HandleInfoKHR-handle-01518
    如果 handle 不为 NULL,则它必须遵守 外部内存句柄类型兼容性 中为 handleType 列出的任何要求

  • VUID-VkImportMemoryWin32HandleInfoKHR-name-01519
    如果 name 不为 NULL,则它必须遵守 外部内存句柄类型兼容性 中为 handleType 列出的任何要求

有效使用(隐式)
  • VUID-VkImportMemoryWin32HandleInfoKHR-sType-sType
    sType 必须VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR

  • VUID-VkImportMemoryWin32HandleInfoKHR-handleType-parameter
    如果 handleType 不为 0,则 handleType 必须是有效的 VkExternalMemoryHandleTypeFlagBits

要导出代表 Vulkan 设备内存对象有效载荷的 Windows 句柄,请调用

// Provided by VK_KHR_external_memory_win32
VkResult vkGetMemoryWin32HandleKHR(
    VkDevice                                    device,
    const VkMemoryGetWin32HandleInfoKHR*        pGetWin32HandleInfo,
    HANDLE*                                     pHandle);
  • device 是创建要导出的设备内存的逻辑设备。

  • pGetWin32HandleInfo 是指向 VkMemoryGetWin32HandleInfoKHR 结构的指针,该结构包含导出操作的参数。

  • pHandle 将返回代表设备内存对象有效载荷的 Windows 句柄。

对于定义为 NT 句柄的句柄类型,vkGetMemoryWin32HandleKHR 返回的句柄由应用程序拥有,并持有对其有效载荷的引用。为避免资源泄漏,应用程序在不再需要这些句柄时,必须使用 CloseHandle 系统调用释放它们的所有权。

非 NT 句柄类型不会为其关联的有效载荷添加引用。如果拥有有效载荷的原始对象被销毁,则共享该有效载荷的所有资源和句柄都将失效。

有效使用(隐式)
  • VUID-vkGetMemoryWin32HandleKHR-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkGetMemoryWin32HandleKHR-pGetWin32HandleInfo-parameter
    pGetWin32HandleInfo 必须是指向有效 VkMemoryGetWin32HandleInfoKHR 结构的有效指针

  • VUID-vkGetMemoryWin32HandleKHR-pHandle-parameter
    pHandle 必须是指向 HANDLE 值的有效指针

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_TOO_MANY_OBJECTS

  • VK_ERROR_OUT_OF_HOST_MEMORY

VkMemoryGetWin32HandleInfoKHR 结构的定义如下:

// Provided by VK_KHR_external_memory_win32
typedef struct VkMemoryGetWin32HandleInfoKHR {
    VkStructureType                       sType;
    const void*                           pNext;
    VkDeviceMemory                        memory;
    VkExternalMemoryHandleTypeFlagBits    handleType;
} VkMemoryGetWin32HandleInfoKHR;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • memory 是要从中导出句柄的内存对象。

  • handleType 是一个 VkExternalMemoryHandleTypeFlagBits 值,指定请求的句柄类型。

返回的句柄的属性取决于 handleType 的值。有关已定义外部内存句柄类型的属性的说明,请参阅 VkExternalMemoryHandleTypeFlagBits

有效用法
  • VUID-VkMemoryGetWin32HandleInfoKHR-handleType-00662
    创建 memory 时,handleType 必须已包含在 VkExportMemoryAllocateInfo::handleTypes

  • VUID-VkMemoryGetWin32HandleInfoKHR-handleType-00663
    如果 handleType 定义为 NT 句柄,则对于 memoryhandleType 的每个有效的唯一组合,必须最多调用一次 vkGetMemoryWin32HandleKHR

  • VUID-VkMemoryGetWin32HandleInfoKHR-handleType-00664
    handleType 必须定义为 NT 句柄或全局共享句柄

有效使用(隐式)
  • VUID-VkMemoryGetWin32HandleInfoKHR-sType-sType
    sType 必须VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR

  • VUID-VkMemoryGetWin32HandleInfoKHR-pNext-pNext
    pNext 必须NULL

  • VUID-VkMemoryGetWin32HandleInfoKHR-memory-parameter
    memory 必须是一个有效的 VkDeviceMemory 句柄。

  • VUID-VkMemoryGetWin32HandleInfoKHR-handleType-parameter
    handleType 必须是有效的 VkExternalMemoryHandleTypeFlagBits

与 Vulkan 兼容的 Windows 内存句柄也可能由非 Vulkan API 使用超出本规范范围的方法创建。要确定导入此类句柄时要使用的正确参数,请调用

// Provided by VK_KHR_external_memory_win32
VkResult vkGetMemoryWin32HandlePropertiesKHR(
    VkDevice                                    device,
    VkExternalMemoryHandleTypeFlagBits          handleType,
    HANDLE                                      handle,
    VkMemoryWin32HandlePropertiesKHR*           pMemoryWin32HandleProperties);
有效用法
  • VUID-vkGetMemoryWin32HandlePropertiesKHR-handle-00665
    handle 必须指向有效的 Windows 内存句柄

  • VUID-vkGetMemoryWin32HandlePropertiesKHR-handleType-00666
    handleType 不能是定义为不透明的句柄类型之一

有效使用(隐式)
  • VUID-vkGetMemoryWin32HandlePropertiesKHR-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkGetMemoryWin32HandlePropertiesKHR-handleType-parameter
    handleType 必须是有效的 VkExternalMemoryHandleTypeFlagBits

  • VUID-vkGetMemoryWin32HandlePropertiesKHR-pMemoryWin32HandleProperties-parameter
    pMemoryWin32HandleProperties 必须是指向 VkMemoryWin32HandlePropertiesKHR 结构的有效指针

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_INVALID_EXTERNAL_HANDLE

返回的 VkMemoryWin32HandlePropertiesKHR 结构定义如下:

// Provided by VK_KHR_external_memory_win32
typedef struct VkMemoryWin32HandlePropertiesKHR {
    VkStructureType    sType;
    void*              pNext;
    uint32_t           memoryTypeBits;
} VkMemoryWin32HandlePropertiesKHR;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • memoryTypeBits 是一个位掩码,其中为指定的 Windows 句柄可以作为导入的每个内存类型设置一个位。

有效使用(隐式)
  • VUID-VkMemoryWin32HandlePropertiesKHR-sType-sType
    sType 必须VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR

  • VUID-VkMemoryWin32HandlePropertiesKHR-pNext-pNext
    pNext 必须NULL

VkExportMemoryAllocateInfoNV::handleTypes 包括 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV 时,将 VkExportMemoryWin32HandleInfoNV 结构添加到 VkExportMemoryAllocateInfoNV 结构的 pNext 链,以指定内存对象外部句柄的安全属性和访问权限。

VkExportMemoryWin32HandleInfoNV 结构的定义如下:

// Provided by VK_NV_external_memory_win32
typedef struct VkExportMemoryWin32HandleInfoNV {
    VkStructureType               sType;
    const void*                   pNext;
    const SECURITY_ATTRIBUTES*    pAttributes;
    DWORD                         dwAccess;
} VkExportMemoryWin32HandleInfoNV;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • pAttributes 是指向 Windows SECURITY_ATTRIBUTES 结构的指针,该结构指定句柄的安全属性。

  • dwAccess 是一个 DWORD,指定句柄的访问权限。

如果此结构不存在,或者如果 pAttributesNULL,则将使用默认的安全描述符值,并且应用程序创建的子进程将不会继承该句柄,如 MSDN 文档“同步对象安全性和访问权限”1中所述。此外,如果该结构不存在,则访问权限将为

DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE

有效使用(隐式)
  • VUID-VkExportMemoryWin32HandleInfoNV-sType-sType
    sType 必须VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV

  • VUID-VkExportMemoryWin32HandleInfoNV-pAttributes-parameter
    如果 pAttributes 不为 NULL,则 pAttributes 必须是指向有效 SECURITY_ATTRIBUTES 值的有效指针

要导入在同一物理设备上但在当前 Vulkan 实例之外创建的内存,请将 VkImportMemoryWin32HandleInfoNV 结构添加到 VkMemoryAllocateInfo 结构的 pNext 链,指定内存的句柄和类型。

VkImportMemoryWin32HandleInfoNV 结构的定义如下:

// Provided by VK_NV_external_memory_win32
typedef struct VkImportMemoryWin32HandleInfoNV {
    VkStructureType                      sType;
    const void*                          pNext;
    VkExternalMemoryHandleTypeFlagsNV    handleType;
    HANDLE                               handle;
} VkImportMemoryWin32HandleInfoNV;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • handleType0 或一个 VkExternalMemoryHandleTypeFlagBitsNV 值,指定 handle 中内存句柄的类型。

  • handle 是指向内存的 Windows HANDLE

如果 handleType0,则此结构会被它所链入的 VkMemoryAllocateInfo 结构的消费者忽略。

有效用法
  • VUID-VkImportMemoryWin32HandleInfoNV-handleType-01327
    handleType 不能设置多个位

  • VUID-VkImportMemoryWin32HandleInfoNV-handle-01328
    handle 必须是有效的内存句柄,该句柄必须按照 handleType 的指定方式获取。

有效使用(隐式)
  • VUID-VkImportMemoryWin32HandleInfoNV-sType-sType
    sType 必须VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV

  • VUID-VkImportMemoryWin32HandleInfoNV-handleType-parameter
    handleType 必须VkExternalMemoryHandleTypeFlagBitsNV 值的有效组合。

可以在 handleType 中设置的位有:

VkImportMemoryWin32HandleInfoNV::handleType 的可能值,用于指定外部内存句柄的类型,如下所示:

// Provided by VK_NV_external_memory_capabilities
typedef enum VkExternalMemoryHandleTypeFlagBitsNV {
    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV = 0x00000001,
    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV = 0x00000002,
    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV = 0x00000004,
    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV = 0x00000008,
} VkExternalMemoryHandleTypeFlagBitsNV;
  • VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV 指定一个由 vkGetMemoryWin32HandleNV 返回的内存句柄。

  • VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV 指定一个由 vkGetMemoryWin32HandleNV 返回的内存句柄,或者使用 DuplicateHandle() 从此类句柄复制而来的句柄。

  • VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV 指定一个由 IDXGIResource1::CreateSharedHandle 返回的有效 NT 内存句柄,或者使用 DuplicateHandle() 从此类句柄复制而来的句柄。

  • VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV 指定一个由 IDXGIResource::GetSharedHandle() 返回的内存句柄。

// Provided by VK_NV_external_memory_capabilities
typedef VkFlags VkExternalMemoryHandleTypeFlagsNV;

VkExternalMemoryHandleTypeFlagsNV 是一个位掩码类型,用于设置零个或多个 VkExternalMemoryHandleTypeFlagBitsNV 的掩码。

要检索使用 VkExportMemoryAllocateInfoNV::handleTypes 设置(包含 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NVVK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV)创建的设备内存对象对应的句柄,请调用:

// Provided by VK_NV_external_memory_win32
VkResult vkGetMemoryWin32HandleNV(
    VkDevice                                    device,
    VkDeviceMemory                              memory,
    VkExternalMemoryHandleTypeFlagsNV           handleType,
    HANDLE*                                     pHandle);
  • device 是拥有内存的逻辑设备。

  • memoryVkDeviceMemory 对象。

  • handleTypeVkExternalMemoryHandleTypeFlagBitsNV 的位掩码,其中包含指定所请求句柄类型的单个位。

  • handle 是指向 Windows HANDLE 的指针,句柄将在其中返回。

有效用法
  • VUID-vkGetMemoryWin32HandleNV-handleType-01326
    handleType 必须是在分配 memory 时在 VkExportMemoryAllocateInfoNV::handleTypes 中指定的标志。

有效使用(隐式)
  • VUID-vkGetMemoryWin32HandleNV-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkGetMemoryWin32HandleNV-memory-parameter
    memory 必须是一个有效的 VkDeviceMemory 句柄。

  • VUID-vkGetMemoryWin32HandleNV-handleType-parameter
    handleType 必须VkExternalMemoryHandleTypeFlagBitsNV 值的有效组合。

  • VUID-vkGetMemoryWin32HandleNV-handleType-requiredbitmask
    handleType 不能0

  • VUID-vkGetMemoryWin32HandleNV-pHandle-parameter
    pHandle 必须是指向 HANDLE 值的有效指针

  • VUID-vkGetMemoryWin32HandleNV-memory-parent
    memory 必须已从 device 创建、分配或检索。

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_TOO_MANY_OBJECTS

  • VK_ERROR_OUT_OF_HOST_MEMORY

文件描述符外部内存

要从 POSIX 文件描述符句柄导入内存,请将 VkImportMemoryFdInfoKHR 结构添加到 VkMemoryAllocateInfo 结构的 pNext 链中。VkImportMemoryFdInfoKHR 结构的定义如下:

// Provided by VK_KHR_external_memory_fd
typedef struct VkImportMemoryFdInfoKHR {
    VkStructureType                       sType;
    const void*                           pNext;
    VkExternalMemoryHandleTypeFlagBits    handleType;
    int                                   fd;
} VkImportMemoryFdInfoKHR;

从文件描述符导入内存会将文件描述符的所有权从应用程序转移到 Vulkan 实现。成功导入后,应用程序不得对文件描述符执行任何操作。导入的内存对象持有对其有效负载的引用。

应用程序可以将相同的负载导入到 Vulkan 的多个实例中,导入到导出该负载的同一实例中,以及多次导入到给定的 Vulkan 实例中。在所有情况下,每个导入操作必须创建一个不同的 VkDeviceMemory 对象。

有效用法
  • VUID-VkImportMemoryFdInfoKHR-handleType-00667
    如果 handleType 不为 0,则它必须支持导入,如 VkExternalImageFormatPropertiesVkExternalBufferProperties 报告的那样

  • VUID-VkImportMemoryFdInfoKHR-fd-00668
    从中导出 fd 的内存必须是在与 device 相同的底层物理设备上创建的。

  • VUID-VkImportMemoryFdInfoKHR-handleType-00669
    如果 handleType 不为 0,则它必须VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BITVK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT

  • VUID-VkImportMemoryFdInfoKHR-handleType-00670
    如果 handleType 不为 0,则 fd 必须handleType 指定的类型的有效句柄。

  • VUID-VkImportMemoryFdInfoKHR-fd-01746
    fd 表示的内存必须是从与 devicehandleType 兼容的物理设备和驱动程序创建的,如外部内存句柄类型兼容性中所述。

  • VUID-VkImportMemoryFdInfoKHR-fd-01520
    fd 必须遵守外部内存句柄类型兼容性中为 handleType 列出的任何要求。

有效使用(隐式)
  • VUID-VkImportMemoryFdInfoKHR-sType-sType
    sType 必须VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR

  • VUID-VkImportMemoryFdInfoKHR-handleType-parameter
    如果 handleType 不为 0,则 handleType 必须是有效的 VkExternalMemoryHandleTypeFlagBits

要导出引用 Vulkan 设备内存对象有效负载的 POSIX 文件描述符,请调用:

// Provided by VK_KHR_external_memory_fd
VkResult vkGetMemoryFdKHR(
    VkDevice                                    device,
    const VkMemoryGetFdInfoKHR*                 pGetFdInfo,
    int*                                        pFd);
  • device 是创建要导出的设备内存的逻辑设备。

  • pGetFdInfo 是指向 VkMemoryGetFdInfoKHR 结构的指针,该结构包含导出操作的参数。

  • pFd 将返回引用设备内存对象有效负载的文件描述符。

vkGetMemoryFdKHR 的每次调用必须创建一个新的文件描述符,该描述符持有对内存对象有效负载的引用,并将文件描述符的所有权转移给应用程序。为避免泄漏资源,应用程序在不再需要文件描述符时,必须使用 close 系统调用释放其所有权,或者通过从中导入 Vulkan 内存对象来释放其所有权。在操作系统支持的情况下,实现必须设置文件描述符,使其在发出 execve 系统调用时自动关闭。

有效使用(隐式)
  • VUID-vkGetMemoryFdKHR-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkGetMemoryFdKHR-pGetFdInfo-parameter
    pGetFdInfo 必须是指向有效的 VkMemoryGetFdInfoKHR 结构的有效指针。

  • VUID-vkGetMemoryFdKHR-pFd-parameter
    pFd 必须是指向 int 值的有效指针。

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_TOO_MANY_OBJECTS

  • VK_ERROR_OUT_OF_HOST_MEMORY

VkMemoryGetFdInfoKHR 结构定义如下:

// Provided by VK_KHR_external_memory_fd
typedef struct VkMemoryGetFdInfoKHR {
    VkStructureType                       sType;
    const void*                           pNext;
    VkDeviceMemory                        memory;
    VkExternalMemoryHandleTypeFlagBits    handleType;
} VkMemoryGetFdInfoKHR;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • memory 是要从中导出句柄的内存对象。

  • handleType 是一个 VkExternalMemoryHandleTypeFlagBits 值,指定请求的句柄类型。

导出的文件描述符的属性取决于 handleType 的值。有关定义的外部内存句柄类型的属性说明,请参阅VkExternalMemoryHandleTypeFlagBits

导出的文件大小可能大于 VkMemoryAllocateInfo::allocationSize 请求的大小。如果 handleTypeVK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,则应用程序可以使用 lseek 查询文件的实际大小。

有效用法
  • VUID-VkMemoryGetFdInfoKHR-handleType-00671
    创建 memory 时,handleType 必须已包含在 VkExportMemoryAllocateInfo::handleTypes

  • VUID-VkMemoryGetFdInfoKHR-handleType-00672
    handleType 必须VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BITVK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT

有效使用(隐式)
  • VUID-VkMemoryGetFdInfoKHR-sType-sType
    sType 必须VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR

  • VUID-VkMemoryGetFdInfoKHR-pNext-pNext
    pNext 必须NULL

  • VUID-VkMemoryGetFdInfoKHR-memory-parameter
    memory 必须是一个有效的 VkDeviceMemory 句柄。

  • VUID-VkMemoryGetFdInfoKHR-handleType-parameter
    handleType 必须是有效的 VkExternalMemoryHandleTypeFlagBits

与 Vulkan 兼容的 POSIX 文件描述符内存句柄可以通过本规范范围之外的方法,由非 Vulkan API 创建。要确定导入此类句柄时使用的正确参数,请调用

// Provided by VK_KHR_external_memory_fd
VkResult vkGetMemoryFdPropertiesKHR(
    VkDevice                                    device,
    VkExternalMemoryHandleTypeFlagBits          handleType,
    int                                         fd,
    VkMemoryFdPropertiesKHR*                    pMemoryFdProperties);
有效用法
  • VUID-vkGetMemoryFdPropertiesKHR-fd-00673
    fd 必须指向有效的 POSIX 文件描述符内存句柄

  • VUID-vkGetMemoryFdPropertiesKHR-handleType-00674
    handleType 必须不是 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT

有效使用(隐式)
  • VUID-vkGetMemoryFdPropertiesKHR-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkGetMemoryFdPropertiesKHR-handleType-parameter
    handleType 必须是有效的 VkExternalMemoryHandleTypeFlagBits

  • VUID-vkGetMemoryFdPropertiesKHR-pMemoryFdProperties-parameter
    pMemoryFdProperties 必须是指向 VkMemoryFdPropertiesKHR 结构的有效指针

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_INVALID_EXTERNAL_HANDLE

返回的 VkMemoryFdPropertiesKHR 结构定义如下

// Provided by VK_KHR_external_memory_fd
typedef struct VkMemoryFdPropertiesKHR {
    VkStructureType    sType;
    void*              pNext;
    uint32_t           memoryTypeBits;
} VkMemoryFdPropertiesKHR;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • memoryTypeBits 是一个位掩码,其中为指定文件描述符可以导入的每个内存类型设置一个位。

有效使用(隐式)
  • VUID-VkMemoryFdPropertiesKHR-sType-sType
    sType 必须VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR

  • VUID-VkMemoryFdPropertiesKHR-pNext-pNext
    pNext 必须NULL

主机外部内存

要从主机指针导入内存,请将 VkImportMemoryHostPointerInfoEXT 结构添加到 VkMemoryAllocateInfo 结构的 pNext 链中。 VkImportMemoryHostPointerInfoEXT 结构定义如下

// Provided by VK_EXT_external_memory_host
typedef struct VkImportMemoryHostPointerInfoEXT {
    VkStructureType                       sType;
    const void*                           pNext;
    VkExternalMemoryHandleTypeFlagBits    handleType;
    void*                                 pHostPointer;
} VkImportMemoryHostPointerInfoEXT;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • handleType 是一个 VkExternalMemoryHandleTypeFlagBits 值,指定句柄类型。

  • pHostPointer 是要从中导入的主机指针。

从主机指针导入内存会在主机和 Vulkan 实现之间共享内存的所有权。应用程序可以继续通过主机指针访问内存,但应用程序有责任按照设备内存对象的主机访问中定义的那样,同步设备和非设备对有效负载的访问。

应用程序可以将相同的有效负载导入到 Vulkan 的多个实例中,以及多次导入到给定的 Vulkan 实例中。但是,由于平台限制,实现可能无法将相同的有效负载多次导入到给定的物理设备中。

由于超出本规范范围的其他特定于平台的限制,从特定主机指针导入内存可能不可行,在这种情况下,实现必须使用错误代码 VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR 来使内存导入操作失败。

从主机指针导入的设备内存对象是否持有对其有效负载的引用是未定义的。因此,应用程序必须确保导入的内存范围在导入的内存对象的生命周期内保持有效和可访问。

实现可以支持为非主机可见的内存类型导入主机指针。在这种情况下,在成功调用 vkAllocateMemory 之后,在 VkDeviceMemory 被销毁之前,应用程序必须不访问从 pHostPointer 导入的内存范围。导入时主机内存的内容变为未定义的,并且在 VkDeviceMemory 被销毁后保持未定义。当 VkDeviceMemory 句柄有效时,应用程序还必须不访问映射到与 pHostPointer 相同物理内存但映射到不同主机指针的主机内存。在通用操作系统上运行的实现应该不支持为非主机可见的内存类型导入主机指针。

使用主机指针来支持非主机可见的分配是一种特定于平台的用例,除非平台指示,否则应用程序不应尝试这样做。

有效用法
  • VUID-VkImportMemoryHostPointerInfoEXT-handleType-01747
    如果 handleType 不为 0,则它必须支持导入,如 VkExternalMemoryProperties 中报告的那样

  • VUID-VkImportMemoryHostPointerInfoEXT-handleType-01748
    如果 handleType 不为 0,则它必须VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXTVK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT

  • VUID-VkImportMemoryHostPointerInfoEXT-pHostPointer-01749
    pHostPointer 必须是指针,该指针与 VkPhysicalDeviceExternalMemoryHostPropertiesEXT::minImportedHostPointerAlignment 的整数倍对齐

  • VUID-VkImportMemoryHostPointerInfoEXT-handleType-01750
    如果 handleTypeVK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,则 pHostPointer 必须是指向 allocationSize 字节的主机内存的指针,其中 allocationSize 是此结构链接到的 VkMemoryAllocateInfo 结构的成员

  • VUID-VkImportMemoryHostPointerInfoEXT-handleType-01751
    如果 handleTypeVK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT,则 pHostPointer 必须是指向 allocationSize 个字节的主机映射外部内存的指针,其中 allocationSize 是此结构链接到的 VkMemoryAllocateInfo 结构的成员。

有效使用(隐式)
  • VUID-VkImportMemoryHostPointerInfoEXT-sType-sType
    sType 必须VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT

  • VUID-VkImportMemoryHostPointerInfoEXT-handleType-parameter
    handleType 必须是有效的 VkExternalMemoryHandleTypeFlagBits

  • VUID-VkImportMemoryHostPointerInfoEXT-pHostPointer-parameter
    pHostPointer 必须是指针值

要确定导入主机指针时要使用的正确参数,请调用

// Provided by VK_EXT_external_memory_host
VkResult vkGetMemoryHostPointerPropertiesEXT(
    VkDevice                                    device,
    VkExternalMemoryHandleTypeFlagBits          handleType,
    const void*                                 pHostPointer,
    VkMemoryHostPointerPropertiesEXT*           pMemoryHostPointerProperties);
  • device 是将要导入 pHostPointer 的逻辑设备。

  • handleType 是一个 VkExternalMemoryHandleTypeFlagBits 值,指定 pHostPointer 句柄的类型。

  • pHostPointer 是要从中导入的主机指针。

  • pMemoryHostPointerProperties 是指向 VkMemoryHostPointerPropertiesEXT 结构的指针,该结构返回主机指针属性。

有效用法
  • VUID-vkGetMemoryHostPointerPropertiesEXT-handleType-01752
    handleType 必须VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXTVK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT

  • VUID-vkGetMemoryHostPointerPropertiesEXT-pHostPointer-01753
    pHostPointer 必须是指针,该指针与 VkPhysicalDeviceExternalMemoryHostPropertiesEXT::minImportedHostPointerAlignment 的整数倍对齐

  • VUID-vkGetMemoryHostPointerPropertiesEXT-handleType-01754
    如果 handleTypeVK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,则 pHostPointer 必须是指向主机内存的指针

  • VUID-vkGetMemoryHostPointerPropertiesEXT-handleType-01755
    如果 handleTypeVK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT,则 pHostPointer 必须是指向主机映射的外部内存的指针

有效使用(隐式)
  • VUID-vkGetMemoryHostPointerPropertiesEXT-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkGetMemoryHostPointerPropertiesEXT-handleType-parameter
    handleType 必须是有效的 VkExternalMemoryHandleTypeFlagBits

  • VUID-vkGetMemoryHostPointerPropertiesEXT-pHostPointer-parameter
    pHostPointer 必须是指针值

  • VUID-vkGetMemoryHostPointerPropertiesEXT-pMemoryHostPointerProperties-parameter
    pMemoryHostPointerProperties 必须是指向 VkMemoryHostPointerPropertiesEXT 结构的有效指针

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_INVALID_EXTERNAL_HANDLE

VkMemoryHostPointerPropertiesEXT 结构定义如下

// Provided by VK_EXT_external_memory_host
typedef struct VkMemoryHostPointerPropertiesEXT {
    VkStructureType    sType;
    void*              pNext;
    uint32_t           memoryTypeBits;
} VkMemoryHostPointerPropertiesEXT;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • memoryTypeBits 是一个位掩码,其中为每个指定主机指针 可以 作为导入的内存类型设置一个位。

memoryTypeBits 返回的值 应该仅包含标识主机可见的内存类型的位。实现 可能 包含标识非主机可见的内存类型的位。此类类型的导入指针的行为由 VkImportMemoryHostPointerInfoEXT 定义。

有效使用(隐式)
  • VUID-VkMemoryHostPointerPropertiesEXT-sType-sType
    sType 必须VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT

  • VUID-VkMemoryHostPointerPropertiesEXT-pNext-pNext
    pNext 必须NULL

Android 硬件缓冲区外部内存

要从 Android 硬件缓冲区导入当前 Vulkan 实例外部创建的内存,请将 VkImportAndroidHardwareBufferInfoANDROID 结构添加到 VkMemoryAllocateInfo 结构的 pNext 链。VkImportAndroidHardwareBufferInfoANDROID 结构定义如下

// Provided by VK_ANDROID_external_memory_android_hardware_buffer
typedef struct VkImportAndroidHardwareBufferInfoANDROID {
    VkStructureType            sType;
    const void*                pNext;
    struct AHardwareBuffer*    buffer;
} VkImportAndroidHardwareBufferInfoANDROID;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • buffer 是要导入的 Android 硬件缓冲区。

如果 vkAllocateMemory 命令成功,则实现 必须 获取对导入的硬件缓冲区的引用,该引用 必须 在释放设备内存对象时释放。如果命令失败,则实现 必须 不保留引用。

有效用法
  • VUID-VkImportAndroidHardwareBufferInfoANDROID-buffer-01880
    如果 buffer 不为 NULL,则 必须 支持导入 Android 硬件缓冲区,如 VkExternalImageFormatPropertiesVkExternalBufferProperties 所报告的那样

  • VUID-VkImportAndroidHardwareBufferInfoANDROID-buffer-01881
    如果 buffer 不为 NULL,则它 必须 是一个有效的 Android 硬件缓冲区对象,其 AHardwareBuffer_Desc::usage 与 Vulkan 兼容,如 Android 硬件缓冲区 中所述

有效使用(隐式)
  • VUID-VkImportAndroidHardwareBufferInfoANDROID-sType-sType
    sType 必须VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID

  • VUID-VkImportAndroidHardwareBufferInfoANDROID-buffer-parameter
    buffer 必须是指向 AHardwareBuffer 值的有效指针

要导出引用 Vulkan 设备内存对象有效负载的 Android 硬件缓冲区,请调用

// Provided by VK_ANDROID_external_memory_android_hardware_buffer
VkResult vkGetMemoryAndroidHardwareBufferANDROID(
    VkDevice                                    device,
    const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo,
    struct AHardwareBuffer**                    pBuffer);
  • device 是创建要导出的设备内存的逻辑设备。

  • pInfo 是指向 VkMemoryGetAndroidHardwareBufferInfoANDROID 结构的指针,该结构包含导出操作的参数。

  • pBuffer 将返回一个 Android 硬件缓冲区,该缓冲区引用设备内存对象的有效负载。

每次调用 vkGetMemoryAndroidHardwareBufferANDROID 必须 返回一个 Android 硬件缓冲区,该缓冲区除了 VkDeviceMemory 持有的引用外,还获得了一个新的引用。为避免资源泄漏,当不再需要引用时,应用程序 必须 通过调用 AHardwareBuffer_release 来释放引用。当在 VkMemoryGetAndroidHardwareBufferInfoANDROID::memory 中使用相同的句柄调用时,vkGetMemoryAndroidHardwareBufferANDROID 必须 返回相同的 Android 硬件缓冲区对象。如果设备内存是通过导入 Android 硬件缓冲区创建的,则 vkGetMemoryAndroidHardwareBufferANDROID 必须 返回相同的 Android 硬件缓冲区对象。

有效使用(隐式)
  • VUID-vkGetMemoryAndroidHardwareBufferANDROID-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkGetMemoryAndroidHardwareBufferANDROID-pInfo-parameter
    pInfo 必须是指向有效 VkMemoryGetAndroidHardwareBufferInfoANDROID 结构的有效指针

  • VUID-vkGetMemoryAndroidHardwareBufferANDROID-pBuffer-parameter
    pBuffer 必须是指向有效 AHardwareBuffer 值指针的有效指针

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_TOO_MANY_OBJECTS

  • VK_ERROR_OUT_OF_HOST_MEMORY

VkMemoryGetAndroidHardwareBufferInfoANDROID 结构定义如下

// Provided by VK_ANDROID_external_memory_android_hardware_buffer
typedef struct VkMemoryGetAndroidHardwareBufferInfoANDROID {
    VkStructureType    sType;
    const void*        pNext;
    VkDeviceMemory     memory;
} VkMemoryGetAndroidHardwareBufferInfoANDROID;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • memory 是内存对象,Android 硬件缓冲区将从该对象导出。

有效用法
  • VUID-VkMemoryGetAndroidHardwareBufferInfoANDROID-handleTypes-01882
    当创建 memory 时,VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID 必须包含在 VkExportMemoryAllocateInfo::handleTypes

  • VUID-VkMemoryGetAndroidHardwareBufferInfoANDROID-pNext-01883
    如果用于分配 memoryVkMemoryAllocateInfopNext 链包含一个 image 成员为非 NULLVkMemoryDedicatedAllocateInfo,则该 image 必须已绑定到 memory

有效使用(隐式)
  • VUID-VkMemoryGetAndroidHardwareBufferInfoANDROID-sType-sType
    sType 必须VK_STRUCTURE_TYPE_MEMORY_GET_ANDROID_HARDWARE_BUFFER_INFO_ANDROID

  • VUID-VkMemoryGetAndroidHardwareBufferInfoANDROID-pNext-pNext
    pNext 必须NULL

  • VUID-VkMemoryGetAndroidHardwareBufferInfoANDROID-memory-parameter
    memory 必须是一个有效的 VkDeviceMemory 句柄。

要确定导入 Android 硬件缓冲区时要使用的内存参数,请调用

// Provided by VK_ANDROID_external_memory_android_hardware_buffer
VkResult vkGetAndroidHardwareBufferPropertiesANDROID(
    VkDevice                                    device,
    const struct AHardwareBuffer*               buffer,
    VkAndroidHardwareBufferPropertiesANDROID*   pProperties);
  • device 是将导入 buffer 的逻辑设备。

  • buffer 是要导入的 Android 硬件缓冲区。

  • pProperties 是指向 VkAndroidHardwareBufferPropertiesANDROID 结构的指针,其中返回 buffer 的属性。

有效用法
  • VUID-vkGetAndroidHardwareBufferPropertiesANDROID-buffer-01884
    buffer 必须是有效的 Android 硬件缓冲区对象,在其 AHardwareBuffer_Desc::usage 中至少有一个 AHARDWAREBUFFER_USAGE_GPU_* 标志

有效使用(隐式)
  • VUID-vkGetAndroidHardwareBufferPropertiesANDROID-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkGetAndroidHardwareBufferPropertiesANDROID-buffer-parameter
    buffer 必须是指向有效 AHardwareBuffer 值的有效指针

  • VUID-vkGetAndroidHardwareBufferPropertiesANDROID-pProperties-parameter
    pProperties 必须是指向 VkAndroidHardwareBufferPropertiesANDROID 结构的有效指针

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR

返回的 VkAndroidHardwareBufferPropertiesANDROID 结构定义如下

// Provided by VK_ANDROID_external_memory_android_hardware_buffer
typedef struct VkAndroidHardwareBufferPropertiesANDROID {
    VkStructureType    sType;
    void*              pNext;
    VkDeviceSize       allocationSize;
    uint32_t           memoryTypeBits;
} VkAndroidHardwareBufferPropertiesANDROID;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • allocationSize 是外部内存的大小

  • memoryTypeBits 是一个位掩码,其中为每个指定的 Android 硬件缓冲区 可以导入的内存类型设置一个位。

有效使用(隐式)

要获取 Android 硬件缓冲区的格式属性,请在传递给 vkGetAndroidHardwareBufferPropertiesANDROIDVkAndroidHardwareBufferPropertiesANDROID 结构的 pNext 链中包含 VkAndroidHardwareBufferFormatPropertiesANDROID 结构。此结构的定义如下

// Provided by VK_ANDROID_external_memory_android_hardware_buffer
typedef struct VkAndroidHardwareBufferFormatPropertiesANDROID {
    VkStructureType                  sType;
    void*                            pNext;
    VkFormat                         format;
    uint64_t                         externalFormat;
    VkFormatFeatureFlags             formatFeatures;
    VkComponentMapping               samplerYcbcrConversionComponents;
    VkSamplerYcbcrModelConversion    suggestedYcbcrModel;
    VkSamplerYcbcrRange              suggestedYcbcrRange;
    VkChromaLocation                 suggestedXChromaOffset;
    VkChromaLocation                 suggestedYChromaOffset;
} VkAndroidHardwareBufferFormatPropertiesANDROID;

如果 Android 硬件缓冲区的格式在格式等效表中列出,则 format 必须具有表中列出的等效 Vulkan 格式。 否则,format 可以VK_FORMAT_UNDEFINED,表示 Android 硬件缓冲区只能与外部格式一起使用。

formatFeatures 成员 必须包括 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BITVK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BITVK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT 中的至少一个,并且 应该包括 VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BITVK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT

formatFeatures 成员仅指示使用从 Android 硬件缓冲区创建的 外部格式图像时可用的功能。 来自格式不是 VK_FORMAT_UNDEFINED 的 Android 硬件缓冲区的图像受从具有适当参数的 vkGetPhysicalDeviceFormatProperties2vkGetPhysicalDeviceImageFormatProperties2 获取的格式功能约束。这些功能集彼此独立,例如,即使非外部格式不支持,外部格式也将支持采样器 Y′CBCR 转换,即使非外部格式支持,也不支持直接渲染到外部格式。

具有相同外部格式的 Android 硬件缓冲区必须formatFeatures 中对 VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BITVK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BITVK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BITVK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BITVK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BITVK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT 具有相同的支持。具有相同外部格式的 Android 硬件缓冲区之间的其他格式特性可能不同。这允许应用程序对具有相同外部格式的任何 Android 硬件缓冲区使用相同的 VkSamplerYcbcrConversion 对象(以及从中创建的采样器和管线)。

如果 format 不是 VK_FORMAT_UNDEFINED,则 samplerYcbcrConversionComponents 的值在用作具有该格式的 VkSamplerYcbcrConversionCreateInfocomponents 成员时必须有效。如果 formatVK_FORMAT_UNDEFINED,则 samplerYcbcrConversionComponents 的所有成员必须标识置换

实现可能并非始终能够确定图像内容的颜色模型、数值范围或色度偏移,因此 VkAndroidHardwareBufferFormatPropertiesANDROID 中的值仅为建议值。应用程序应该将这些值视为在没有通过其他方式获得的更可靠信息时使用的合理默认值。如果底层物理设备也可以通过具有 GL_OES_EGL_image_external 扩展的 OpenGL ES 使用,则该实现应该建议产生与通过使用等效采样器参数在 OpenGL ES 中通过 samplerExternalOES 对同一外部图像进行采样所获得的类似采样值的值。

由于 GL_OES_EGL_image_external 不需要与 Vulkan 相同的采样和转换计算,因此在某些实现上,API 之间实现相同的结果可能是不可能的。

有效使用(隐式)
  • VUID-VkAndroidHardwareBufferFormatPropertiesANDROID-sType-sType
    sType 必须VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID

Android 硬件缓冲区的格式属性可以通过在传递给 vkGetAndroidHardwareBufferPropertiesANDROIDVkAndroidHardwareBufferPropertiesANDROID 结构的 pNext 链中包含一个 VkAndroidHardwareBufferFormatProperties2ANDROID 结构来获取。此结构定义为

// Provided by VK_ANDROID_external_memory_android_hardware_buffer with VK_KHR_format_feature_flags2 or VK_VERSION_1_3
typedef struct VkAndroidHardwareBufferFormatProperties2ANDROID {
    VkStructureType                  sType;
    void*                            pNext;
    VkFormat                         format;
    uint64_t                         externalFormat;
    VkFormatFeatureFlags2            formatFeatures;
    VkComponentMapping               samplerYcbcrConversionComponents;
    VkSamplerYcbcrModelConversion    suggestedYcbcrModel;
    VkSamplerYcbcrRange              suggestedYcbcrRange;
    VkChromaLocation                 suggestedXChromaOffset;
    VkChromaLocation                 suggestedYChromaOffset;
} VkAndroidHardwareBufferFormatProperties2ANDROID;

formatFeatures 中报告的位必须包括 VkAndroidHardwareBufferFormatPropertiesANDROID::formatFeatures 的相应字段中报告的位。

有效使用(隐式)
  • VUID-VkAndroidHardwareBufferFormatProperties2ANDROID-sType-sType
    sType 必须VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID

// Provided by VK_ANDROID_external_format_resolve
typedef struct VkAndroidHardwareBufferFormatResolvePropertiesANDROID {
    VkStructureType    sType;
    void*              pNext;
    VkFormat           colorAttachmentFormat;
} VkAndroidHardwareBufferFormatResolvePropertiesANDROID;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • colorAttachmentFormat 是一个 VkFormat,指定当解析为指定的外部格式时,用于颜色附件图像的颜色附件图像的格式。如果实现支持指定外部格式的外部格式解析,则此值将是一种颜色格式,支持 VkFormatProperties::optimalTilingFeatures 中的 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT,由 vkGetPhysicalDeviceFormatProperties 返回,且 format 等于 colorAttachmentFormat。如果不支持外部格式解析,则此值将为 VK_FORMAT_UNDEFINED

使用 GRALLOC_USAGE_HW_RENDER 标志创建的任何 Android 硬件缓冲区必须以某种方式在 Vulkan 中可渲染,要么

有效使用(隐式)
  • VUID-VkAndroidHardwareBufferFormatResolvePropertiesANDROID-sType-sType
    sType 必须VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_RESOLVE_PROPERTIES_ANDROID

远程设备外部内存

要导出表示远程设备可访问的 Vulkan 设备内存对象负载的地址,请调用

// Provided by VK_NV_external_memory_rdma
VkResult vkGetMemoryRemoteAddressNV(
    VkDevice                                    device,
    const VkMemoryGetRemoteAddressInfoNV*       pMemoryGetRemoteAddressInfo,
    VkRemoteAddressNV*                          pAddress);
  • device 是创建要导出的设备内存的逻辑设备。

  • pMemoryGetRemoteAddressInfo 是指向 VkMemoryGetRemoteAddressInfoNV 结构的指针,该结构包含导出操作的参数。

  • pAddress 是指向 VkRemoteAddressNV 值的指针,在该值中返回表示设备内存对象负载的地址。

所涉及设备的内核模式驱动程序之间可能需要更多通信。此信息不在此文档的范围之内,应从设备供应商处请求。

有效使用(隐式)
  • VUID-vkGetMemoryRemoteAddressNV-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkGetMemoryRemoteAddressNV-pMemoryGetRemoteAddressInfo-parameter
    pMemoryGetRemoteAddressInfo 必须是指向有效 VkMemoryGetRemoteAddressInfoNV 结构的有效指针

  • VUID-vkGetMemoryRemoteAddressNV-pAddress-parameter
    pAddress 必须是指向 VkRemoteAddressNV 值的有效指针

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_INVALID_EXTERNAL_HANDLE

VkMemoryGetRemoteAddressInfoNV 结构定义为

// Provided by VK_NV_external_memory_rdma
typedef struct VkMemoryGetRemoteAddressInfoNV {
    VkStructureType                       sType;
    const void*                           pNext;
    VkDeviceMemory                        memory;
    VkExternalMemoryHandleTypeFlagBits    handleType;
} VkMemoryGetRemoteAddressInfoNV;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • memory 是从中导出远程可访问地址的内存对象。

  • handleType 是请求的句柄类型。

有效用法
  • VUID-VkMemoryGetRemoteAddressInfoNV-handleType-04966
    创建 memory 时,handleType 必须已包含在 VkExportMemoryAllocateInfo::handleTypes

有效使用(隐式)
  • VUID-VkMemoryGetRemoteAddressInfoNV-sType-sType
    sType 必须VK_STRUCTURE_TYPE_MEMORY_GET_REMOTE_ADDRESS_INFO_NV

  • VUID-VkMemoryGetRemoteAddressInfoNV-pNext-pNext
    pNext 必须NULL

  • VUID-VkMemoryGetRemoteAddressInfoNV-memory-parameter
    memory 必须是一个有效的 VkDeviceMemory 句柄。

  • VUID-VkMemoryGetRemoteAddressInfoNV-handleType-parameter
    handleType 必须是有效的 VkExternalMemoryHandleTypeFlagBits

VkRemoteAddressNV 表示远程设备可访问的内存对象的地址,如在 vkGetMemoryRemoteAddressNV::pAddress 中返回。

// Provided by VK_NV_external_memory_rdma
typedef void* VkRemoteAddressNV;

Fuchsia 外部内存

在 Fuchsia 上,当分配可能从其他设备、进程或 Vulkan 实例导入的内存时,将 VkImportMemoryZirconHandleInfoFUCHSIA 结构添加到 VkMemoryAllocateInfo 结构的 pNext 链中。

Fuchsia 上的外部内存使用 zx_handle_t 类型的 VMO 句柄进行导入和导出。外部内存的 VMO 句柄通常从 Fuchsia 的 Sysmem 服务或诸如 zx_vmo_create() 等系统调用中获取。导入的 VMO 句柄也可以通过从另一个 Vulkan 实例导出它们来获得,如导出 Fuchsia 设备内存中所述。

将 VMO 句柄导入到 Vulkan 实例会将句柄的所有权从应用程序转移到该实例。应用程序在成功导入后必须不对该句柄执行任何操作。

应用程序可以将相同的底层内存导入到 Vulkan 的多个实例中,从导出它的同一个实例导入,以及多次导入到给定的 Vulkan 实例中。在所有情况下,每次导入操作必须创建一个不同的 VkDeviceMemory 对象。

导入 Fuchsia 外部内存

VkImportMemoryZirconHandleInfoFUCHSIA 结构定义如下

// Provided by VK_FUCHSIA_external_memory
typedef struct VkImportMemoryZirconHandleInfoFUCHSIA {
    VkStructureType                       sType;
    const void*                           pNext;
    VkExternalMemoryHandleTypeFlagBits    handleType;
    zx_handle_t                           handle;
} VkImportMemoryZirconHandleInfoFUCHSIA;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • handleType 是一个 VkExternalMemoryHandleTypeFlagBits 值,指定 handle 的类型。

  • handle 是一个指向外部内存的 zx_handle_t (Zircon) 句柄。

有效用法
  • VUID-VkImportMemoryZirconHandleInfoFUCHSIA-handleType-04771
    handleType 必须VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA

  • VUID-VkImportMemoryZirconHandleInfoFUCHSIA-handle-04772
    handle 必须是有效的 VMO 句柄

有效使用(隐式)
  • VUID-VkImportMemoryZirconHandleInfoFUCHSIA-sType-sType
    sType 必须VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA

  • VUID-VkImportMemoryZirconHandleInfoFUCHSIA-handleType-parameter
    如果 handleType 不为 0,则 handleType 必须是有效的 VkExternalMemoryHandleTypeFlagBits

要获取 VkMemoryAllocateInfo 结构的 memoryTypeIndex,请调用 vkGetMemoryZirconHandlePropertiesFUCHSIA

// Provided by VK_FUCHSIA_external_memory
VkResult vkGetMemoryZirconHandlePropertiesFUCHSIA(
    VkDevice                                    device,
    VkExternalMemoryHandleTypeFlagBits          handleType,
    zx_handle_t                                 zirconHandle,
    VkMemoryZirconHandlePropertiesFUCHSIA*      pMemoryZirconHandleProperties);
有效用法
  • VUID-vkGetMemoryZirconHandlePropertiesFUCHSIA-handleType-04773
    handleType 必须VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA

  • VUID-vkGetMemoryZirconHandlePropertiesFUCHSIA-zirconHandle-04774
    zirconHandle 必须引用一个有效的 VMO

有效使用(隐式)
  • VUID-vkGetMemoryZirconHandlePropertiesFUCHSIA-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkGetMemoryZirconHandlePropertiesFUCHSIA-handleType-parameter
    handleType 必须是有效的 VkExternalMemoryHandleTypeFlagBits

  • VUID-vkGetMemoryZirconHandlePropertiesFUCHSIA-pMemoryZirconHandleProperties-parameter
    pMemoryZirconHandleProperties 必须是指向 VkMemoryZirconHandlePropertiesFUCHSIA 结构的有效指针

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_INVALID_EXTERNAL_HANDLE

VkMemoryZirconHandlePropertiesFUCHSIA 结构定义如下

// Provided by VK_FUCHSIA_external_memory
typedef struct VkMemoryZirconHandlePropertiesFUCHSIA {
    VkStructureType    sType;
    void*              pNext;
    uint32_t           memoryTypeBits;
} VkMemoryZirconHandlePropertiesFUCHSIA;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • memoryTypeBits 是一个位掩码,其中包含为指定句柄可以导入的每个内存类型设置的位。

有效使用(隐式)
  • VUID-VkMemoryZirconHandlePropertiesFUCHSIA-sType-sType
    sType 必须VK_STRUCTURE_TYPE_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA

  • VUID-VkMemoryZirconHandlePropertiesFUCHSIA-pNext-pNext
    pNext 必须NULL

vkGetMemoryZirconHandlePropertiesFUCHSIA 成功填充 pMemoryZirconHandleProperties 后,将 VkMemoryAllocateInfo 的 memoryTypeIndex 字段分配给 VkMemoryZirconHandlePropertiesFUCHSIA 的 memoryTypeBits 字段中设置了位的内存类型。

导出 Fuchsia 设备内存

与导入类似,从 Vulkan 导出 VMO 句柄会将句柄的所有权从 Vulkan 实例转移到应用程序。应用程序负责在使用完毕后使用 zx_handle_close() 关闭句柄。

要将设备内存导出为可由另一个实例、设备或进程使用的 Zircon 句柄,请使用以下命令检索 VkDeviceMemory 的句柄

// Provided by VK_FUCHSIA_external_memory
VkResult vkGetMemoryZirconHandleFUCHSIA(
    VkDevice                                    device,
    const VkMemoryGetZirconHandleInfoFUCHSIA*   pGetZirconHandleInfo,
    zx_handle_t*                                pZirconHandle);
有效使用(隐式)
  • VUID-vkGetMemoryZirconHandleFUCHSIA-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkGetMemoryZirconHandleFUCHSIA-pGetZirconHandleInfo-parameter
    pGetZirconHandleInfo 必须是指向有效的 VkMemoryGetZirconHandleInfoFUCHSIA 结构的有效指针

  • VUID-vkGetMemoryZirconHandleFUCHSIA-pZirconHandle-parameter
    pZirconHandle 必须是指向 zx_handle_t 值的有效指针

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_TOO_MANY_OBJECTS

  • VK_ERROR_OUT_OF_HOST_MEMORY

VkMemoryGetZirconHandleInfoFUCHSIA 定义如下

// Provided by VK_FUCHSIA_external_memory
typedef struct VkMemoryGetZirconHandleInfoFUCHSIA {
    VkStructureType                       sType;
    const void*                           pNext;
    VkDeviceMemory                        memory;
    VkExternalMemoryHandleTypeFlagBits    handleType;
} VkMemoryGetZirconHandleInfoFUCHSIA;
有效用法
  • VUID-VkMemoryGetZirconHandleInfoFUCHSIA-handleType-04775
    handleType 必须VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA

  • VUID-VkMemoryGetZirconHandleInfoFUCHSIA-handleType-04776
    当分配外部内存时,handleType 必须已包含在 VkExportMemoryAllocateInfo 结构的 handleTypes 字段中

有效使用(隐式)
  • VUID-VkMemoryGetZirconHandleInfoFUCHSIA-sType-sType
    sType 必须VK_STRUCTURE_TYPE_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA

  • VUID-VkMemoryGetZirconHandleInfoFUCHSIA-pNext-pNext
    pNext 必须NULL

  • VUID-VkMemoryGetZirconHandleInfoFUCHSIA-memory-parameter
    memory 必须是一个有效的 VkDeviceMemory 句柄。

  • VUID-VkMemoryGetZirconHandleInfoFUCHSIA-handleType-parameter
    handleType 必须是有效的 VkExternalMemoryHandleTypeFlagBits

现在已经获得了 pZirconHandle 的结果,可以使用 vkGetMemoryZirconHandlePropertiesFUCHSIA 获取句柄的内存属性,如上所述,将解引用后检索到的 pZirconHandle 替换为 zirconHandle 参数。

Metal 对象

在 Apple 设备平台上,基于 Metal 构建的 Vulkan 实现,并实现了 VK_EXT_metal_objects 扩展,支持导入和导出与特定 Vulkan 对象关联的底层 Metal 对象的功能。

可以使用 vkExportMetalObjectsEXT 命令的 VkExportMetalObjectsInfoEXT 参数的 pNext 链,从这些 Vulkan 对象中导出与某些 Vulkan 对象关联的底层 Metal 对象。

通过在 vkAllocateMemory 命令的 VkMemoryAllocateInfo 结构的 pNext 链中包含 VkImportMetalBufferInfoEXT 结构,可以将 VkDeviceMemory 对象分配到现有的 MTLBuffer 对象上。

通过在 vkCreateImage 命令的 VkImageCreateInfo 结构的 pNext 链中包含 VkImportMetalIOSurfaceInfoEXTVkImportMetalTextureInfoEXT 结构,可以在现有的 IOSurface 对象或一个或多个现有的 Metal MTLTexture 对象上创建新的 VkImage 对象。

要从 Vulkan 对象导出 Metal 对象,应用程序**必须**首先在创建 Vulkan 对象时通过在相应的 Vulkan 对象创建命令的 VkInstanceCreateInfoVkMemoryAllocateInfoVkImageCreateInfoVkImageViewCreateInfoVkBufferViewCreateInfoVkSemaphoreCreateInfoVkEventCreateInfopNext 链中包含一个或多个 VkExportMetalObjectCreateInfoEXT 结构,来表明导出意图。

VkExportMetalObjectCreateInfoEXT 结构定义如下:

// Provided by VK_EXT_metal_objects
typedef struct VkExportMetalObjectCreateInfoEXT {
    VkStructureType                       sType;
    const void*                           pNext;
    VkExportMetalObjectTypeFlagBitsEXT    exportObjectType;
} VkExportMetalObjectCreateInfoEXT;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • exportObjectType 是一个 VkExportMetalObjectTypeFlagBitsEXT,指示应用程序可能请求从 Vulkan 对象导出的 Metal 对象的类型。

有效使用(隐式)
  • VUID-VkExportMetalObjectCreateInfoEXT-sType-sType
    sType **必须**为 VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT

  • VUID-VkExportMetalObjectCreateInfoEXT-exportObjectType-parameter
    如果 exportObjectType 不为 0,则 exportObjectType **必须**是一个有效的 VkExportMetalObjectTypeFlagBitsEXT

指示可能从相应 Vulkan 对象导出的 Metal 对象类型的位如下:

// Provided by VK_EXT_metal_objects
typedef enum VkExportMetalObjectTypeFlagBitsEXT {
    VK_EXPORT_METAL_OBJECT_TYPE_METAL_DEVICE_BIT_EXT = 0x00000001,
    VK_EXPORT_METAL_OBJECT_TYPE_METAL_COMMAND_QUEUE_BIT_EXT = 0x00000002,
    VK_EXPORT_METAL_OBJECT_TYPE_METAL_BUFFER_BIT_EXT = 0x00000004,
    VK_EXPORT_METAL_OBJECT_TYPE_METAL_TEXTURE_BIT_EXT = 0x00000008,
    VK_EXPORT_METAL_OBJECT_TYPE_METAL_IOSURFACE_BIT_EXT = 0x00000010,
    VK_EXPORT_METAL_OBJECT_TYPE_METAL_SHARED_EVENT_BIT_EXT = 0x00000020,
} VkExportMetalObjectTypeFlagBitsEXT;
  • VK_EXPORT_METAL_OBJECT_TYPE_METAL_DEVICE_BIT_EXT 指定可以导出 Metal MTLDevice

  • VK_EXPORT_METAL_OBJECT_TYPE_METAL_COMMAND_QUEUE_BIT_EXT 指定可以导出 Metal MTLCommandQueue

  • VK_EXPORT_METAL_OBJECT_TYPE_METAL_BUFFER_BIT_EXT 指定可以导出 Metal MTLBuffer

  • VK_EXPORT_METAL_OBJECT_TYPE_METAL_TEXTURE_BIT_EXT 指定可以导出 Metal MTLTexture

  • VK_EXPORT_METAL_OBJECT_TYPE_METAL_IOSURFACE_BIT_EXT 指定可以导出 Metal IOSurface

  • VK_EXPORT_METAL_OBJECT_TYPE_METAL_SHARED_EVENT_BIT_EXT 指定可以导出 Metal MTLSharedEvent

// Provided by VK_EXT_metal_objects
typedef VkFlags VkExportMetalObjectTypeFlagsEXT;

VkExportMetalObjectTypeFlagsEXT 是一个位掩码类型,用于设置零个或多个 VkExportMetalObjectTypeFlagBitsEXT 的掩码。

要导出 Vulkan 对象下的 Metal 对象,请调用

// Provided by VK_EXT_metal_objects
void vkExportMetalObjectsEXT(
    VkDevice                                    device,
    VkExportMetalObjectsInfoEXT*                pMetalObjectsInfo);
  • device 是创建 Vulkan 对象的设备。

  • pMetalObjectsInfo 是指向 VkExportMetalObjectsInfoEXT 结构的指针,该结构的 pNext 链包含多个结构,每个结构标识一个 Vulkan 对象,并提供一个指针,通过该指针返回 Metal 对象。

有效使用(隐式)
  • VUID-vkExportMetalObjectsEXT-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkExportMetalObjectsEXT-pMetalObjectsInfo-parameter
    pMetalObjectsInfo **必须**是指向 VkExportMetalObjectsInfoEXT 结构的有效指针

VkExportMetalObjectsInfoEXT 结构定义如下:

// Provided by VK_EXT_metal_objects
typedef struct VkExportMetalObjectsInfoEXT {
    VkStructureType    sType;
    const void*        pNext;
} VkExportMetalObjectsInfoEXT;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

有效用法
有效使用(隐式)

要导出与 VkDevice 对象关联的 VkPhysicalDevice 对应的 Metal MTLDevice 对象,请在 vkExportMetalObjectsEXT 调用的 pMetalObjectsInfo 参数的 pNext 链中包含 VkExportMetalDeviceInfoEXT 结构。

VkExportMetalDeviceInfoEXT 结构定义如下:

// Provided by VK_EXT_metal_objects
typedef struct VkExportMetalDeviceInfoEXT {
    VkStructureType    sType;
    const void*        pNext;
    MTLDevice_id       mtlDevice;
} VkExportMetalDeviceInfoEXT;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • mtlDevice 是与调用中标识的 VkDevice 对象关联的 VkPhysicalDevice 对应的 Metal id<MTLDevice> 对象。实现将在该成员中返回 MTLDevice,如果找不到与 VkPhysicalDevice 对象对应的 MTLDevice,则返回 NULL

有效使用(隐式)
  • VUID-VkExportMetalDeviceInfoEXT-sType-sType
    sType 必须VK_STRUCTURE_TYPE_EXPORT_METAL_DEVICE_INFO_EXT

类型 id<MTLDevice> 在 Apple 的 Metal 框架中定义,但为了避免不必要的编译时依赖,Vulkan 头文件中提供了 MTLDevice_id 的不完整类型定义。

// Provided by VK_EXT_metal_objects
#ifdef __OBJC__
@protocol MTLDevice;
typedef __unsafe_unretained id<MTLDevice> MTLDevice_id;
#else
typedef void* MTLDevice_id;
#endif

要导出 VkQueue 对象对应的 Metal MTLCommandQueue 对象,请在 vkExportMetalObjectsEXT 调用的 pMetalObjectsInfo 参数的 pNext 链中包含 VkExportMetalCommandQueueInfoEXT 结构。

VkExportMetalCommandQueueInfoEXT 结构定义如下:

// Provided by VK_EXT_metal_objects
typedef struct VkExportMetalCommandQueueInfoEXT {
    VkStructureType       sType;
    const void*           pNext;
    VkQueue               queue;
    MTLCommandQueue_id    mtlCommandQueue;
} VkExportMetalCommandQueueInfoEXT;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • queue 是一个 VkQueue

  • mtlCommandQueuequeueVkQueue 对象对应的 Metal id<MTLCommandQueue> 对象。实现将在该成员中返回 MTLCommandQueue,如果找不到与 VkQueue 对象对应的 MTLCommandQueue,则返回 NULL

有效使用(隐式)
  • VUID-VkExportMetalCommandQueueInfoEXT-sType-sType
    sType 必须VK_STRUCTURE_TYPE_EXPORT_METAL_COMMAND_QUEUE_INFO_EXT

  • VUID-VkExportMetalCommandQueueInfoEXT-queue-parameter
    queue 必须是有效的 VkQueue 句柄。

类型 id<MTLCommandQueue> 在 Apple 的 Metal 框架中定义,但为了避免不必要的编译时依赖,Vulkan 头文件中提供了 MTLCommandQueue_id 的不完整类型定义。

// Provided by VK_EXT_metal_objects
#ifdef __OBJC__
@protocol MTLCommandQueue;
typedef __unsafe_unretained id<MTLCommandQueue> MTLCommandQueue_id;
#else
typedef void* MTLCommandQueue_id;
#endif

要导出 VkDeviceMemory 对象对应的 Metal MTLBuffer 对象,请在 vkExportMetalObjectsEXT 调用的 pMetalObjectsInfo 参数的 pNext 链中包含 VkExportMetalBufferInfoEXT 结构。

VkExportMetalBufferInfoEXT 结构定义如下:

// Provided by VK_EXT_metal_objects
typedef struct VkExportMetalBufferInfoEXT {
    VkStructureType    sType;
    const void*        pNext;
    VkDeviceMemory     memory;
    MTLBuffer_id       mtlBuffer;
} VkExportMetalBufferInfoEXT;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • memory 是一个 VkDeviceMemory

  • mtlBuffermemoryVkDeviceMemory 对象对应的 Metal id<MTLBuffer> 对象。实现将在该成员中返回 MTLBuffer,如果找不到与 VkDeviceMemory 对象对应的 MTLBuffer,则返回 NULL

有效使用(隐式)
  • VUID-VkExportMetalBufferInfoEXT-sType-sType
    sType 必须VK_STRUCTURE_TYPE_EXPORT_METAL_BUFFER_INFO_EXT

  • VUID-VkExportMetalBufferInfoEXT-memory-parameter
    memory 必须是一个有效的 VkDeviceMemory 句柄。

要导入 Metal MTLBuffer 对象以作为 VkDeviceMemory 对象的基础,请在 vkAllocateMemory 命令中 VkMemoryAllocateInfo 结构的 pNext 链中包含 VkImportMetalBufferInfoEXT 结构。

VkImportMetalBufferInfoEXT 结构定义如下:

// Provided by VK_EXT_metal_objects
typedef struct VkImportMetalBufferInfoEXT {
    VkStructureType    sType;
    const void*        pNext;
    MTLBuffer_id       mtlBuffer;
} VkImportMetalBufferInfoEXT;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • mtlBuffer 是作为 VkDeviceMemory 基础的 Metal id<MTLBuffer> 对象。

应用程序必须确保 id<MTLBuffer> 对象的配置与 VkDeviceMemory 的配置兼容。否则会导致未定义的行为。

有效使用(隐式)
  • VUID-VkImportMetalBufferInfoEXT-sType-sType
    sType 必须VK_STRUCTURE_TYPE_IMPORT_METAL_BUFFER_INFO_EXT

类型 id<MTLBuffer> 在 Apple 的 Metal 框架中定义,但为了避免不必要的编译时依赖,Vulkan 头文件中提供了 MTLBuffer_id 的不完整类型定义。

// Provided by VK_EXT_metal_objects
#ifdef __OBJC__
@protocol MTLBuffer;
typedef __unsafe_unretained id<MTLBuffer> MTLBuffer_id;
#else
typedef void* MTLBuffer_id;
#endif

要导出 VkImageVkImageViewVkBufferView 对象对应的 Metal MTLTexture 对象,请在 vkExportMetalObjectsEXT 调用的 pMetalObjectsInfo 参数的 pNext 链中包含 VkExportMetalTextureInfoEXT 结构。

VkExportMetalTextureInfoEXT 结构定义如下:

// Provided by VK_EXT_metal_objects
typedef struct VkExportMetalTextureInfoEXT {
    VkStructureType          sType;
    const void*              pNext;
    VkImage                  image;
    VkImageView              imageView;
    VkBufferView             bufferView;
    VkImageAspectFlagBits    plane;
    MTLTexture_id            mtlTexture;
} VkExportMetalTextureInfoEXT;
有效使用(隐式)
  • VUID-VkExportMetalTextureInfoEXT-sType-sType
    sType 必须VK_STRUCTURE_TYPE_EXPORT_METAL_TEXTURE_INFO_EXT

  • VUID-VkExportMetalTextureInfoEXT-image-parameter
    如果 image 不为 VK_NULL_HANDLE,则 image 必须 是一个有效的 VkImage 句柄

  • VUID-VkExportMetalTextureInfoEXT-imageView-parameter
    如果 imageView 不是 VK_NULL_HANDLE,则 imageView 必须 是一个有效的 VkImageView 句柄

  • VUID-VkExportMetalTextureInfoEXT-bufferView-parameter
    如果 bufferView 不是 VK_NULL_HANDLE,则 bufferView 必须 是一个有效的 VkBufferView 句柄

  • VUID-VkExportMetalTextureInfoEXT-plane-parameter
    plane 必须 是一个有效的 VkImageAspectFlagBits

  • VUID-VkExportMetalTextureInfoEXT-commonparent
    bufferViewimageimageView 中每个非忽略参数的有效句柄必须从同一个 VkDevice 创建、分配或检索。

要将一个或多个现有的 Metal MTLTexture 对象导入到一个 VkImage 对象之下,请在 vkCreateImage 命令的 VkImageCreateInfo 结构的 pNext 链中包含一个或多个 VkImportMetalTextureInfoEXT 结构。

VkImportMetalTextureInfoEXT 结构定义如下:

// Provided by VK_EXT_metal_objects
typedef struct VkImportMetalTextureInfoEXT {
    VkStructureType          sType;
    const void*              pNext;
    VkImageAspectFlagBits    plane;
    MTLTexture_id            mtlTexture;
} VkImportMetalTextureInfoEXT;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • plane 指定 VkImage 的平面,id<MTLTexture> 对象应附加到该平面。

  • mtlTexture 是要作为 VkImage 平面基础的 Metal id<MTLTexture> 对象。

pNext必须VkImage 中的每个平面包含一个 VkImportMetalTextureInfoEXT 结构。应用程序必须确保 Metal id<MTLTexture> 对象的配置与 VkImage 的配置兼容。否则会导致未定义的行为。

有效使用(隐式)
  • VUID-VkImportMetalTextureInfoEXT-sType-sType
    sType 必须VK_STRUCTURE_TYPE_IMPORT_METAL_TEXTURE_INFO_EXT

  • VUID-VkImportMetalTextureInfoEXT-plane-parameter
    plane 必须 是一个有效的 VkImageAspectFlagBits

类型 id<MTLTexture> 在 Apple 的 Metal 框架中定义,但是为了删除不必要的编译时依赖项,在 Vulkan 头文件中提供了 MTLTexture_id 的不完整类型定义

// Provided by VK_EXT_metal_objects
#ifdef __OBJC__
@protocol MTLTexture;
typedef __unsafe_unretained id<MTLTexture> MTLTexture_id;
#else
typedef void* MTLTexture_id;
#endif

要导出作为 VkImage 对象基础的 Metal IOSurfaceRef 对象,请在 vkExportMetalObjectsEXT 调用的 pMetalObjectsInfo 参数的 pNext 链中包含 VkExportMetalIOSurfaceInfoEXT 结构。

VkExportMetalIOSurfaceInfoEXT 结构定义如下:

// Provided by VK_EXT_metal_objects
typedef struct VkExportMetalIOSurfaceInfoEXT {
    VkStructureType    sType;
    const void*        pNext;
    VkImage            image;
    IOSurfaceRef       ioSurface;
} VkExportMetalIOSurfaceInfoEXT;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • image 是一个 VkImage

  • ioSurfaceimage 中作为 VkImage 对象基础的 Metal IOSurfaceRef 对象。 如果在 VkImage 对象下找不到 IOSurfaceRef,则实现将在此成员中返回 IOSurfaceRef,否则将返回 NULL

有效使用(隐式)
  • VUID-VkExportMetalIOSurfaceInfoEXT-sType-sType
    sType 必须VK_STRUCTURE_TYPE_EXPORT_METAL_IO_SURFACE_INFO_EXT

  • VUID-VkExportMetalIOSurfaceInfoEXT-image-parameter
    image 必须 是一个有效的 VkImage 句柄

要导入或创建作为 VkImage 对象基础的 Metal IOSurfaceRef 对象,请在 vkCreateImage 命令的 VkImageCreateInfo 结构的 pNext 链中包含 VkImportMetalIOSurfaceInfoEXT 结构。

VkImportMetalIOSurfaceInfoEXT 结构定义如下:

// Provided by VK_EXT_metal_objects
typedef struct VkImportMetalIOSurfaceInfoEXT {
    VkStructureType    sType;
    const void*        pNext;
    IOSurfaceRef       ioSurface;
} VkImportMetalIOSurfaceInfoEXT;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • ioSurfaceVK_NULL_HANDLE 或要作为 VkImage 基础的 Metal IOSurfaceRef 对象。

如果 ioSurface 不是 VK_NULL_HANDLE,它将被用来作为 VkImage 的基础。如果 ioSurfaceVK_NULL_HANDLE,则实现将创建一个新的 IOSurface 来作为 VkImage 的基础。

如果提供了,应用程序必须确保 IOSurfaceRef 对象的配置与 VkImage 的配置兼容。否则会导致未定义的行为。

有效使用(隐式)
  • VUID-VkImportMetalIOSurfaceInfoEXT-sType-sType
    sType 必须VK_STRUCTURE_TYPE_IMPORT_METAL_IO_SURFACE_INFO_EXT

类型 IOSurfaceRef 在 Apple 的 CoreGraphics 框架中定义,但是为了删除不必要的编译时依赖项,在 Vulkan 头文件中提供了 IOSurfaceRef 的不完整类型定义。

// Provided by VK_EXT_metal_objects
typedef struct __IOSurface* IOSurfaceRef;

要导出作为 VkSemaphoreVkEvent 对象基础的 Metal MTLSharedEvent 对象,请在 vkExportMetalObjectsEXT 调用的 pMetalObjectsInfo 参数的 pNext 链中包含 VkExportMetalSharedEventInfoEXT 结构。

VkExportMetalSharedEventInfoEXT 结构定义如下:

// Provided by VK_EXT_metal_objects
typedef struct VkExportMetalSharedEventInfoEXT {
    VkStructureType      sType;
    const void*          pNext;
    VkSemaphore          semaphore;
    VkEvent              event;
    MTLSharedEvent_id    mtlSharedEvent;
} VkExportMetalSharedEventInfoEXT;
有效使用(隐式)
  • VUID-VkExportMetalSharedEventInfoEXT-sType-sType
    sType 必须VK_STRUCTURE_TYPE_EXPORT_METAL_SHARED_EVENT_INFO_EXT

  • VUID-VkExportMetalSharedEventInfoEXT-semaphore-parameter
    如果 semaphore 不是 VK_NULL_HANDLE,则 semaphore 必须 是一个有效的 VkSemaphore 句柄

  • VUID-VkExportMetalSharedEventInfoEXT-event-parameter
    如果 event 不是 VK_NULL_HANDLE,则 event 必须 是一个有效的 VkEvent 句柄

  • VUID-VkExportMetalSharedEventInfoEXT-commonparent
    eventsemaphore 中每个非忽略参数的有效句柄必须从同一个 VkDevice 创建、分配或检索。

要将 Metal id<MTLSharedEvent> 对象导入以作为 VkSemaphoreVkEvent 对象的基础,请在 VkSemaphoreCreateInfoVkEventCreateInfo 结构的 pNext 链中包含一个 VkImportMetalSharedEventInfoEXT 结构,并分别在 vkCreateSemaphorevkCreateEvent 命令中使用。

VkImportMetalSharedEventInfoEXT 结构定义如下:

// Provided by VK_EXT_metal_objects
typedef struct VkImportMetalSharedEventInfoEXT {
    VkStructureType      sType;
    const void*          pNext;
    MTLSharedEvent_id    mtlSharedEvent;
} VkImportMetalSharedEventInfoEXT;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • mtlSharedEvent 是 Metal 的 id<MTLSharedEvent> 对象,它将作为 VkSemaphoreVkEvent 的基础。

如果 VkSemaphoreCreateInfo 结构的 pNext 链同时包含 VkImportMetalSharedEventInfoEXTVkSemaphoreTypeCreateInfo,则导入的 id<MTLSharedEvent> 对象的 signaledValue 属性将被设置为 VkSemaphoreTypeCreateInfo::initialValue

有效使用(隐式)
  • VUID-VkImportMetalSharedEventInfoEXT-sType-sType
    sType 必须VK_STRUCTURE_TYPE_IMPORT_METAL_SHARED_EVENT_INFO_EXT

类型 id<MTLSharedEvent> 在 Apple 的 Metal 框架中定义,但为了消除不必要的编译时依赖,Vulkan 头部文件中提供了 MTLSharedEvent_id 的不完整类型定义。

// Provided by VK_EXT_metal_objects
#ifdef __OBJC__
@protocol MTLSharedEvent;
typedef __unsafe_unretained id<MTLSharedEvent> MTLSharedEvent_id;
#else
typedef void* MTLSharedEvent_id;
#endif

QNX 屏幕缓冲区外部内存

要从 QNX 屏幕缓冲区导入在当前 Vulkan 实例外部创建的内存,请将 VkImportScreenBufferInfoQNX 结构添加到 VkMemoryAllocateInfo 结构的 pNext 链中。VkImportScreenBufferInfoQNX 结构定义如下:

// Provided by VK_QNX_external_memory_screen_buffer
typedef struct VkImportScreenBufferInfoQNX {
    VkStructureType           sType;
    const void*               pNext;
    struct _screen_buffer*    buffer;
} VkImportScreenBufferInfoQNX;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • buffer 是指向 struct _screen_buffer 的指针,即要导入的 QNX 屏幕缓冲区。

实现 可能 不会获取对导入的屏幕缓冲区的引用。因此,应用程序 必须 确保 buffer 引用的对象在它导入的设备内存被使用期间保持有效。

有效用法
有效使用(隐式)
  • VUID-VkImportScreenBufferInfoQNX-sType-sType
    sType 必须VK_STRUCTURE_TYPE_IMPORT_SCREEN_BUFFER_INFO_QNX

要确定导入 QNX 屏幕缓冲区时要使用的内存参数,请调用

// Provided by VK_QNX_external_memory_screen_buffer
VkResult vkGetScreenBufferPropertiesQNX(
    VkDevice                                    device,
    const struct _screen_buffer*                buffer,
    VkScreenBufferPropertiesQNX*                pProperties);
  • device 是将导入 buffer 的逻辑设备。

  • buffer 是要导入的 QNX 屏幕缓冲区。

  • pProperties 是指向 VkScreenBufferPropertiesQNX 结构的指针,该结构返回 buffer 的属性。

有效用法
有效使用(隐式)
  • VUID-vkGetScreenBufferPropertiesQNX-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkGetScreenBufferPropertiesQNX-buffer-parameter
    buffer 必须是指向有效 _screen_buffer 值的有效指针。

  • VUID-vkGetScreenBufferPropertiesQNX-pProperties-parameter
    pProperties 必须是指向 VkScreenBufferPropertiesQNX 结构的有效指针。

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR

返回的 VkScreenBufferPropertiesQNX 结构定义如下:

// Provided by VK_QNX_external_memory_screen_buffer
typedef struct VkScreenBufferPropertiesQNX {
    VkStructureType    sType;
    void*              pNext;
    VkDeviceSize       allocationSize;
    uint32_t           memoryTypeBits;
} VkScreenBufferPropertiesQNX;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • allocationSize 是外部内存的大小。

  • memoryTypeBits 是一个位掩码,其中为每个指定的屏幕缓冲区 可以 导入为的内存类型设置一位。

有效使用(隐式)
  • VUID-VkScreenBufferPropertiesQNX-sType-sType
    sType 必须VK_STRUCTURE_TYPE_SCREEN_BUFFER_PROPERTIES_QNX

  • VUID-VkScreenBufferPropertiesQNX-pNext-pNext
    pNext 必须NULL 或指向 VkScreenBufferFormatPropertiesQNX 的有效实例的指针。

  • VUID-VkScreenBufferPropertiesQNX-sType-unique
    pNext 链中每个结构的 sType必须是唯一的

要获取 QNX 屏幕缓冲区的格式属性,请在传递给 vkGetScreenBufferPropertiesQNXVkScreenBufferPropertiesQNX 结构的 pNext 链中包含一个 VkScreenBufferFormatPropertiesQNX 结构。此结构定义如下:

// Provided by VK_QNX_external_memory_screen_buffer
typedef struct VkScreenBufferFormatPropertiesQNX {
    VkStructureType                  sType;
    void*                            pNext;
    VkFormat                         format;
    uint64_t                         externalFormat;
    uint64_t                         screenUsage;
    VkFormatFeatureFlags             formatFeatures;
    VkComponentMapping               samplerYcbcrConversionComponents;
    VkSamplerYcbcrModelConversion    suggestedYcbcrModel;
    VkSamplerYcbcrRange              suggestedYcbcrRange;
    VkChromaLocation                 suggestedXChromaOffset;
    VkChromaLocation                 suggestedYChromaOffset;
} VkScreenBufferFormatPropertiesQNX;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • format 是对应于屏幕缓冲区格式的 Vulkan 格式,如果不存在等效的 Vulkan 格式,则为 VK_FORMAT_UNDEFINED

  • externalFormat 是一个实现定义的外部格式标识符,用于 VkExternalFormatQNX。它 必须 非零。

  • screenUsage 是 QNX 屏幕缓冲区的实现定义的外部使用标识符。

  • formatFeatures 描述了当与从 buffer 导入的内存绑定的图像一起使用时,此外部格式的功能。

  • samplerYcbcrConversionComponents 是在 VkSamplerYcbcrConversionCreateInfo应该 使用的组件混合。

  • suggestedYcbcrModel 是建议在 VkSamplerYcbcrConversionCreateInfo 中使用的颜色模型。

  • suggestedYcbcrRange 是建议在 VkSamplerYcbcrConversionCreateInfo 中使用的数值范围。

  • suggestedXChromaOffset 是建议在 VkSamplerYcbcrConversionCreateInfo 中使用的 X 色度偏移。

  • suggestedYChromaOffset 是建议在 VkSamplerYcbcrConversionCreateInfo 中使用的 Y 色度偏移。

如果 QNX 屏幕缓冲区具有 QNX 屏幕格式等效表中列出的格式之一,则 format 必须具有表中列出的等效 Vulkan 格式。否则,format 可以VK_FORMAT_UNDEFINED,表示 QNX 屏幕缓冲区 只能 与外部格式一起使用。formatFeatures 成员 必须 包含 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT,并且 应该 包含 VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BITVK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT

有效使用(隐式)
  • VUID-VkScreenBufferFormatPropertiesQNX-sType-sType
    sType 必须VK_STRUCTURE_TYPE_SCREEN_BUFFER_FORMAT_PROPERTIES_QNX

设备组内存分配

如果 VkMemoryAllocateInfopNext 链中包含 VkMemoryAllocateFlagsInfo 结构,则该结构包含控制将分配多少内存实例的标志和设备掩码。

VkMemoryAllocateFlagsInfo 结构定义如下:

// Provided by VK_VERSION_1_1
typedef struct VkMemoryAllocateFlagsInfo {
    VkStructureType          sType;
    const void*              pNext;
    VkMemoryAllocateFlags    flags;
    uint32_t                 deviceMask;
} VkMemoryAllocateFlagsInfo;

或等效的

// Provided by VK_KHR_device_group
typedef VkMemoryAllocateFlagsInfo VkMemoryAllocateFlagsInfoKHR;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • flags 是控制分配的 VkMemoryAllocateFlagBits 的位掩码。

  • deviceMask 是逻辑设备中物理设备的掩码,指示如果 flags 中设置了 VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT,则 必须 在掩码中的每个设备上分配内存。

如果未设置 VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT,则分配的实例数量取决于内存堆中是否设置了 VK_MEMORY_HEAP_MULTI_INSTANCE_BIT。如果设置了 VK_MEMORY_HEAP_MULTI_INSTANCE_BIT,则会为逻辑设备中的每个物理设备分配内存(如同 deviceMask 为所有设备索引设置了位)。如果未设置 VK_MEMORY_HEAP_MULTI_INSTANCE_BIT,则会分配单个内存实例(如同 deviceMask 设置为 1)。

在某些实现中,即使 deviceMask 排除了一些设备,从多实例堆分配的内存可能会消耗所有物理设备上的内存。如果 VkPhysicalDeviceGroupProperties::subsetAllocationVK_TRUE,则仅为设备掩码中的设备消耗内存。

实际上,多实例堆上的大多数分配将在所有物理设备上进行分配。单播分配支持是少数分配的可选优化。

有效用法
  • VUID-VkMemoryAllocateFlagsInfo-deviceMask-00675
    如果设置了 VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT,则 deviceMask 必须是有效的设备掩码

  • VUID-VkMemoryAllocateFlagsInfo-deviceMask-00676
    如果设置了 VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT,则 deviceMask 不能为零

有效使用(隐式)
  • VUID-VkMemoryAllocateFlagsInfo-sType-sType
    sType 必须VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO

  • VUID-VkMemoryAllocateFlagsInfo-flags-parameter
    flags 必须VkMemoryAllocateFlagBits 值的有效组合

可以在 VkMemoryAllocateFlagsInfo::flags 中设置的用于控制设备内存分配的位有:

// Provided by VK_VERSION_1_1
typedef enum VkMemoryAllocateFlagBits {
    VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT = 0x00000001,
  // Provided by VK_VERSION_1_2
    VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT = 0x00000002,
  // Provided by VK_VERSION_1_2
    VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT = 0x00000004,
  // Provided by VK_KHR_device_group
    VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHR = VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT,
  // Provided by VK_KHR_buffer_device_address
    VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
  // Provided by VK_KHR_buffer_device_address
    VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT_KHR = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT,
} VkMemoryAllocateFlagBits;

或等效的

// Provided by VK_KHR_device_group
typedef VkMemoryAllocateFlagBits VkMemoryAllocateFlagBitsKHR;
  • VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT 指定将为 VkMemoryAllocateFlagsInfo::deviceMask 中的设备分配内存。

  • VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT 指定内存可以附加到使用 usage 中设置的 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT 位创建的缓冲区对象,并且可以通过 vkGetDeviceMemoryOpaqueCaptureAddress 使用内存句柄来检索不透明地址。

  • VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT 指定内存的地址可以被保存并在后续运行中重复使用(例如,用于跟踪捕获和重放),有关更多详细信息,请参见 VkBufferOpaqueCaptureAddressCreateInfo

// Provided by VK_VERSION_1_1
typedef VkFlags VkMemoryAllocateFlags;

或等效的

// Provided by VK_KHR_device_group
typedef VkMemoryAllocateFlags VkMemoryAllocateFlagsKHR;

VkMemoryAllocateFlags 是一个位掩码类型,用于设置零个或多个 VkMemoryAllocateFlagBits 的掩码。

不透明捕获地址分配

要为内存分配请求特定的设备地址,请将 VkMemoryOpaqueCaptureAddressAllocateInfo 结构添加到 VkMemoryAllocateInfo 结构的 pNext 链中。VkMemoryOpaqueCaptureAddressAllocateInfo 结构的定义如下:

// Provided by VK_VERSION_1_2
typedef struct VkMemoryOpaqueCaptureAddressAllocateInfo {
    VkStructureType    sType;
    const void*        pNext;
    uint64_t           opaqueCaptureAddress;
} VkMemoryOpaqueCaptureAddressAllocateInfo;

或等效的

// Provided by VK_KHR_buffer_device_address
typedef VkMemoryOpaqueCaptureAddressAllocateInfo VkMemoryOpaqueCaptureAddressAllocateInfoKHR;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • opaqueCaptureAddress 是为内存分配请求的不透明捕获地址。

如果 opaqueCaptureAddress 为零,则不请求特定地址。

如果 opaqueCaptureAddress 不为零,则它应该是从同一实现上以相同方式创建的内存分配的 vkGetDeviceMemoryOpaqueCaptureAddress 中检索的地址。

在大多数情况下,非零 opaqueAddress 预计是从以相同方式创建的内存分配的 vkGetDeviceMemoryOpaqueCaptureAddress 中检索的地址。如果不是这种情况,则很可能会发生 VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS 错误。

但是,这不是严格的要求,因为跟踪捕获/重放工具可能需要调整导入内存的内存分配参数。

如果此结构不存在,则如同 opaqueCaptureAddress 为零。

有效使用(隐式)
  • VUID-VkMemoryOpaqueCaptureAddressAllocateInfo-sType-sType
    sType 必须VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO

释放设备内存

要释放内存对象,请调用

// Provided by VK_VERSION_1_0
void vkFreeMemory(
    VkDevice                                    device,
    VkDeviceMemory                              memory,
    const VkAllocationCallbacks*                pAllocator);
  • device 是拥有内存的逻辑设备。

  • memory 是要释放的 VkDeviceMemory 对象。

  • pAllocator 控制主机内存分配,如内存分配章节中所述。

在释放内存对象之前,应用程序必须确保设备不再使用该内存对象,例如,在挂起状态下的命令缓冲区中。内存可以在仍然绑定到资源时释放,但这些资源之后必须不再使用。释放内存对象会释放它对其有效负载所持有的引用(如果有)。如果仍然有任何绑定的图像或缓冲区,则内存对象的有效负载可能不会立即被实现释放,但必须在所有绑定的图像和缓冲区都被销毁时释放。一旦释放了对有效负载的所有引用,它就会返回到从中分配的堆。

内存对象如何绑定到图像和缓冲区在 资源内存关联 部分中有详细描述。

如果在释放时内存对象被映射,则它会被隐式取消映射。

下文所述,当内存对象被取消映射时,主机写入不会被隐式刷新,但实现必须保证未刷新的写入不会影响任何其他内存。

有效用法
  • VUID-vkFreeMemory-memory-00677
    所有提交的引用 memory 的命令(通过图像或缓冲区)必须已完成执行

有效使用(隐式)
  • VUID-vkFreeMemory-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkFreeMemory-memory-parameter
    如果 memory 不是 VK_NULL_HANDLE,则 memory 必须是有效的 VkDeviceMemory 句柄

  • VUID-vkFreeMemory-pAllocator-parameter
    如果 pAllocator 不是 NULL,则 pAllocator 必须是指向有效 VkAllocationCallbacks 结构的有效指针。

  • VUID-vkFreeMemory-memory-parent
    如果 memory 是有效句柄,则它必须是从 device 创建、分配或检索的

主机同步
  • memory 的主机访问必须进行外部同步

主机对设备内存对象的访问

使用 vkAllocateMemory 创建的内存对象不能直接被主机访问。

使用内存属性 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT 创建的内存对象被认为是可映射的。内存对象必须是可映射的,才能成功地在主机上映射。

要检索可映射内存对象区域的主机虚拟地址指针,请调用

// Provided by VK_VERSION_1_0
VkResult vkMapMemory(
    VkDevice                                    device,
    VkDeviceMemory                              memory,
    VkDeviceSize                                offset,
    VkDeviceSize                                size,
    VkMemoryMapFlags                            flags,
    void**                                      ppData);
  • device 是拥有内存的逻辑设备。

  • memory 是要映射的 VkDeviceMemory 对象。

  • offset 是从内存对象开始的基于零的字节偏移量。

  • size 是要映射的内存范围的大小,或者 VK_WHOLE_SIZE 表示从 offset 映射到分配的末尾。

  • flagsVkMemoryMapFlagBits 的位掩码,指定内存映射操作的其他参数。

  • ppData 是指向 void* 变量的指针,在该变量中返回指向映射范围开始位置的主机可访问指针。返回的指针的值减去 offset 必须VkPhysicalDeviceLimits::minMemoryMapAlignment 对齐。

在成功调用 vkMapMemory 后,内存对象 memory 被认为当前是主机映射的

在已经是主机映射的内存对象上调用 vkMapMemory 是一个应用程序错误。

如果实现无法分配适当大小的连续虚拟地址范围(例如,由于虚拟地址空间碎片或平台限制),则 vkMapMemory 将会失败。在这种情况下,vkMapMemory 必须 返回 VK_ERROR_MEMORY_MAP_FAILED。应用程序可以通过减小映射范围的大小和/或使用 vkUnmapMemory 删除不必要的映射来提高成功的可能性。

vkMapMemory 不会检查设备内存是否在返回主机可访问指针之前正在使用。应用程序必须保证在主机从该范围读取或写入之前,任何先前提交的写入此范围的命令都已完成;并且在主机写入该区域之前,任何先前提交的从该范围读取的命令都已完成(有关满足此类保证的详细信息,请参见 此处)。如果设备内存是在未设置 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT 的情况下分配的,则必须为扩展范围做出这些保证:应用程序必须将范围的起始位置向下舍入到 VkPhysicalDeviceLimits::nonCoherentAtomSize 的最接近的倍数,并将范围的结束位置向上舍入到 VkPhysicalDeviceLimits::nonCoherentAtomSize 的最接近的倍数。

当一段设备内存被主机映射时,应用程序负责同步该内存范围的设备和主机访问。

应用程序开发人员务必仔细熟悉同步和缓存控制章节中描述的所有机制,因为它们对于维护内存访问顺序至关重要。

调用 vkMapMemory 相当于调用带有空 pNext 链的 vkMapMemory2

有效用法
  • VUID-vkMapMemory-memory-00678
    memory 必须当前未被主机映射

  • VUID-vkMapMemory-offset-00679
    offset 必须小于 memory 的大小

  • VUID-vkMapMemory-size-00680
    如果 size 不等于 VK_WHOLE_SIZE,则 size 必须大于 0

  • VUID-vkMapMemory-size-00681
    如果 size 不等于 VK_WHOLE_SIZE,则 size 必须小于或等于 memory 的大小减去 offset 的值

  • VUID-vkMapMemory-memory-00682
    memory 必须使用报告 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT 的内存类型创建

  • VUID-vkMapMemory-memory-00683
    memory 必须不是使用多个实例分配的

  • VUID-vkMapMemory-flags-09568
    VK_MEMORY_MAP_PLACED_BIT_EXT 必须未在 flags 中设置

有效使用(隐式)
  • VUID-vkMapMemory-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkMapMemory-memory-parameter
    memory 必须是一个有效的 VkDeviceMemory 句柄。

  • VUID-vkMapMemory-flags-parameter
    flags 必须VkMemoryMapFlagBits 值的有效组合

  • VUID-vkMapMemory-ppData-parameter
    ppData 必须是指向指针值的有效指针

  • VUID-vkMapMemory-memory-parent
    memory 必须已从 device 创建、分配或检索。

主机同步
  • memory 的主机访问必须进行外部同步

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

  • VK_ERROR_MEMORY_MAP_FAILED

可以在 vkMapMemory::flagsVkMemoryMapInfo::flags 中设置的位,指定内存映射的附加属性,包括

// Provided by VK_VERSION_1_0
typedef enum VkMemoryMapFlagBits {
  // Provided by VK_EXT_map_memory_placed
    VK_MEMORY_MAP_PLACED_BIT_EXT = 0x00000001,
} VkMemoryMapFlagBits;
  • VK_MEMORY_MAP_PLACED_BIT_EXT 请求实现将内存映射放置在应用程序通过 VkMemoryMapPlacedInfoEXT::pPlacedAddress 指定的虚拟地址处,替换该地址处的任何现有映射。此标志必须不与 vkMapMemory 一起使用,因为没有办法指定放置地址。

// Provided by VK_VERSION_1_0
typedef VkFlags VkMemoryMapFlags;

VkMemoryMapFlags 是一种位掩码类型,用于设置零个或多个 VkMemoryMapFlagBits 的掩码。

或者,要检索可映射内存对象区域的主机虚拟地址指针,请调用

// Provided by VK_VERSION_1_4
VkResult vkMapMemory2(
    VkDevice                                    device,
    const VkMemoryMapInfo*                      pMemoryMapInfo,
    void**                                      ppData);

或等效命令

// Provided by VK_KHR_map_memory2
VkResult vkMapMemory2KHR(
    VkDevice                                    device,
    const VkMemoryMapInfo*                      pMemoryMapInfo,
    void**                                      ppData);
  • device 是拥有内存的逻辑设备。

  • pMemoryMapInfo 是指向 VkMemoryMapInfo 结构的指针,该结构描述了映射的参数。

  • ppData 是指向 void * 变量的指针,该变量中返回指向映射范围起点的可主机访问指针。此指针减去 VkMemoryMapInfo::offset 的结果必须至少与 VkPhysicalDeviceLimits::minMemoryMapAlignment 对齐。

此函数的行为与 vkMapMemory 完全相同,只是它通过可扩展的结构指针而不是直接作为函数参数获取其参数。

有效使用(隐式)
  • VUID-vkMapMemory2-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkMapMemory2-pMemoryMapInfo-parameter
    pMemoryMapInfo 必须是指向有效的 VkMemoryMapInfo 结构的有效指针

  • VUID-vkMapMemory2-ppData-parameter
    ppData 必须是指向指针值的有效指针

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

  • VK_ERROR_MEMORY_MAP_FAILED

VkMemoryMapInfo 结构的定义如下:

// Provided by VK_VERSION_1_4
typedef struct VkMemoryMapInfo {
    VkStructureType     sType;
    const void*         pNext;
    VkMemoryMapFlags    flags;
    VkDeviceMemory      memory;
    VkDeviceSize        offset;
    VkDeviceSize        size;
} VkMemoryMapInfo;

或等效的

// Provided by VK_KHR_map_memory2
typedef VkMemoryMapInfo VkMemoryMapInfoKHR;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • flagsVkMemoryMapFlagBits 的位掩码,指定内存映射操作的其他参数。

  • memory 是要映射的 VkDeviceMemory 对象。

  • offset 是从内存对象开始的基于零的字节偏移量。

  • size 是要映射的内存范围的大小,或者 VK_WHOLE_SIZE 表示从 offset 映射到分配的末尾。

有效用法
  • VUID-VkMemoryMapInfo-memory-07958
    memory 必须当前未被主机映射

  • VUID-VkMemoryMapInfo-offset-07959
    offset 必须小于 memory 的大小

  • VUID-VkMemoryMapInfo-size-07960
    如果 size 不等于 VK_WHOLE_SIZE,则 size 必须大于 0

  • VUID-VkMemoryMapInfo-size-07961
    如果 size 不等于 VK_WHOLE_SIZE,则 size 必须小于或等于 memory 的大小减去 offset 的值

  • VUID-VkMemoryMapInfo-memory-07962
    memory 必须使用报告 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT 的内存类型创建

  • VUID-VkMemoryMapInfo-memory-07963
    memory 必须不是使用多个实例分配的

  • VUID-VkMemoryMapInfo-flags-09569
    如果 flags 中设置了 VK_MEMORY_MAP_PLACED_BIT_EXT,则必须启用 memoryMapPlaced 功能

  • VUID-VkMemoryMapInfo-flags-09570
    如果在 flags 中设置了 VK_MEMORY_MAP_PLACED_BIT_EXT,则 pNext必须包含一个 VkMemoryMapPlacedInfoEXT 结构体,并且 VkMemoryMapPlacedInfoEXT::pPlacedAddress 必须不能为 NULL

  • VUID-VkMemoryMapInfo-flags-09571
    如果在 flags 中设置了 VK_MEMORY_MAP_PLACED_BIT_EXT,并且 memoryMapRangePlaced 特性未启用,则 offset 必须为零。

  • VUID-VkMemoryMapInfo-flags-09572
    如果在 flags 中设置了 VK_MEMORY_MAP_PLACED_BIT_EXT,并且 memoryMapRangePlaced 特性未启用,则 size 必须VK_WHOLE_SIZEVkMemoryAllocateInfo::allocationSize

  • VUID-VkMemoryMapInfo-flags-09573
    如果在 flags 中设置了 VK_MEMORY_MAP_PLACED_BIT_EXT,并且 memoryMapRangePlaced 特性已启用,则 offset 必须对齐到 VkPhysicalDeviceMapMemoryPlacedPropertiesEXT::minPlacedMemoryMapAlignment 的整数倍。

  • VUID-VkMemoryMapInfo-flags-09574
    如果在 flags 中设置了 VK_MEMORY_MAP_PLACED_BIT_EXT,并且 size 不为 VK_WHOLE_SIZE,则 size 必须对齐到 VkPhysicalDeviceMapMemoryPlacedPropertiesEXT::minPlacedMemoryMapAlignment 的整数倍。

  • VUID-VkMemoryMapInfo-flags-09651
    如果在 flags 中设置了 VK_MEMORY_MAP_PLACED_BIT_EXT,并且 sizeVK_WHOLE_SIZE,则 VkMemoryAllocateInfo::allocationSize 必须对齐到 VkPhysicalDeviceMapMemoryPlacedPropertiesEXT::minPlacedMemoryMapAlignment 的整数倍。

  • VUID-VkMemoryMapInfo-flags-09575
    如果在 flags 中设置了 VK_MEMORY_MAP_PLACED_BIT_EXT,则内存对象必须没有从 VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXTVK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT 句柄类型导入。

有效使用(隐式)
  • VUID-VkMemoryMapInfo-sType-sType
    sType 必须VK_STRUCTURE_TYPE_MEMORY_MAP_INFO

  • VUID-VkMemoryMapInfo-pNext-pNext
    pNext 必须NULL 或指向 VkMemoryMapPlacedInfoEXT 有效实例的指针。

  • VUID-VkMemoryMapInfo-sType-unique
    pNext 链中每个结构的 sType必须是唯一的

  • VUID-VkMemoryMapInfo-flags-parameter
    flags 必须VkMemoryMapFlagBits 值的有效组合

  • VUID-VkMemoryMapInfo-memory-parameter
    memory 必须是一个有效的 VkDeviceMemory 句柄。

主机同步
  • memory 的主机访问必须进行外部同步

如果 VkMemoryMapInfo::flags 中设置了 VK_MEMORY_MAP_PLACED_BIT_EXT,并且 VkMemoryMapInfopNext 链包含一个 VkMemoryMapPlacedInfoEXT 结构体,则该结构体指定了内存映射的放置地址。实现将在指定的地址放置内存映射,替换指定内存范围内的任何现有映射。以这种方式替换内存映射不会隐式取消映射 Vulkan 内存对象。相反,应用程序必须确保没有其他 Vulkan 内存对象映射在指定的虚拟地址范围内的任何位置。如果成功,ppData 将设置为与 VkMemoryMapPlacedInfoEXT::pPlacedAddress 相同的值,并且 vkMapMemory2 将返回 VK_SUCCESS。如果由于任何原因无法将映射放置在请求的地址,则内存对象将保持未映射状态,并且 vkMapMemory2 将返回 VK_ERROR_MEMORY_MAP_FAILED

VkMemoryMapPlacedInfoEXT 结构体定义如下:

// Provided by VK_EXT_map_memory_placed
typedef struct VkMemoryMapPlacedInfoEXT {
    VkStructureType    sType;
    const void*        pNext;
    void*              pPlacedAddress;
} VkMemoryMapPlacedInfoEXT;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • pPlacedAddress 是放置地址的虚拟地址。如果 VkMemoryMapInfo::flags 不包含 VK_MEMORY_MAP_PLACED_BIT_EXT,则此值将被忽略。

有效用法
  • VUID-VkMemoryMapPlacedInfoEXT-flags-09576
    如果 VkMemoryMapInfo::flags 包含 VK_MEMORY_MAP_PLACED_BIT_EXT,则 pPlacedAddress 必须不为 NULL

  • VUID-VkMemoryMapPlacedInfoEXT-pPlacedAddress-09577
    pPlacedAddress 必须对齐到 VkPhysicalDeviceMapMemoryPlacedPropertiesEXT::minPlacedMemoryMapAlignment 的整数倍。

  • VUID-VkMemoryMapPlacedInfoEXT-pPlacedAddress-09578
    pPlacedAddressVkMemoryMapInfo::size 指定的地址范围必须不与任何现有的 Vulkan 内存对象映射重叠。

有效使用(隐式)
  • VUID-VkMemoryMapPlacedInfoEXT-sType-sType
    sType 必须VK_STRUCTURE_TYPE_MEMORY_MAP_PLACED_INFO_EXT

提供了两个命令,以使应用程序能够处理非一致性内存分配:vkFlushMappedMemoryRangesvkInvalidateMappedMemoryRanges

如果内存对象是在设置了 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT 的情况下创建的,则 vkFlushMappedMemoryRangesvkInvalidateMappedMemoryRanges 是不必要的,并且可能会产生性能成本。但是,仍然需要在设备上管理可用性和可见性操作。有关更多信息,请参见主机访问类型的说明。

虽然从 VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXTVK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT 句柄类型导入的内存对象本身就映射到主机地址空间,但除非使用 vkMapMemory 显式映射到主机,否则它们不被认为是主机映射的设备内存。这意味着,对于通过导入时指定的原始主机指针在此类内存上执行的主机访问,刷新或使主机缓存失效是应用程序的责任,并且必须使用平台提供的适当的同步原语执行,这些同步原语超出了 Vulkan 的范围。但是,vkFlushMappedMemoryRangesvkInvalidateMappedMemoryRanges 仍然可以用于此类内存对象,以同步通过 vkMapMemory 返回的主机映射设备内存范围的主机指针执行的主机访问。

在成功调用 vkMapMemoryvkMapMemory2 后,内存对象 memory 被认为是当前主机映射的

要刷新主机缓存中非一致性内存的范围,请调用

// Provided by VK_VERSION_1_0
VkResult vkFlushMappedMemoryRanges(
    VkDevice                                    device,
    uint32_t                                    memoryRangeCount,
    const VkMappedMemoryRange*                  pMemoryRanges);
  • device 是拥有内存范围的逻辑设备。

  • memoryRangeCountpMemoryRanges 数组的长度。

  • pMemoryRanges 是一个指向 VkMappedMemoryRange 结构体数组的指针,这些结构体描述了需要刷新的内存范围。

vkFlushMappedMemoryRanges 保证了主机对 pMemoryRanges 描述的内存范围的写入对主机内存域可用,这样它们可以通过使用 VK_ACCESS_HOST_WRITE_BIT 访问类型内存域操作,对设备内存域可用。

第一个同步范围包括所有在其之前发生的主机操作,这些操作由主机内存模型定义。

注意

某些系统允许不直接与主机内存模型集成的写入;这些写入必须由应用程序手动同步。一个例子是 x86 上的非临时存储指令;为了确保这些操作发生在提交之前,应用程序应该调用 _mm_sfence()

第二个同步范围为空。

第一个访问范围包括对指定内存范围的主机写入。

注意

当主机对内存位置的写入以这种方式可用时,内存位置所在的每个完整对齐的 nonCoherentAtomSize 字节集也将变得可用,就好像它们是由主机写入的一样。例如,当 nonCoherentAtomSize 为 128 时,如果应用程序通过主机映射写入内存对象的第一个字节,则此命令将使内存对象的头 128 个字节可用。虽然接下来的 127 个字节的值将保持不变,但这确实算作同步的访问,因此必须小心避免数据竞争。

第二个访问范围为空。

取消映射非一致性内存不会隐式刷新主机映射的内存,并且未刷新的主机写入可能永远对设备不可见。但是,实现必须确保未刷新的写入不会对任何其他内存可见。

上述保证避免了以下场景中潜在的内存损坏:在将内存对象取消映射(或释放)之前,主机对映射的内存对象的写入尚未刷新,并且该虚拟地址范围随后被重新用于不同的映射(或内存分配)。

有效使用(隐式)
  • VUID-vkFlushMappedMemoryRanges-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkFlushMappedMemoryRanges-pMemoryRanges-parameter
    pMemoryRanges 必须是指向 memoryRangeCount 个有效 VkMappedMemoryRange 结构体数组的有效指针

  • VUID-vkFlushMappedMemoryRanges-memoryRangeCount-arraylength
    memoryRangeCount 必须大于 0

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

要使主机缓存中的非一致性内存范围失效,请调用

// Provided by VK_VERSION_1_0
VkResult vkInvalidateMappedMemoryRanges(
    VkDevice                                    device,
    uint32_t                                    memoryRangeCount,
    const VkMappedMemoryRange*                  pMemoryRanges);
  • device 是拥有内存范围的逻辑设备。

  • memoryRangeCountpMemoryRanges 数组的长度。

  • pMemoryRanges 是一个指向 VkMappedMemoryRange 结构体数组的指针,这些结构体描述了需要失效的内存范围。

vkInvalidateMappedMemoryRanges 保证了设备对 pMemoryRanges 描述的内存范围的写入,这些写入已使用 VK_ACCESS_HOST_WRITE_BITVK_ACCESS_HOST_READ_BIT 访问类型对主机内存域可用,并且对主机可见。如果主机写入并失效了非一致性内存范围,但没有先刷新,则其内容是未定义的

第一个同步范围包括所有在其之前发生的主机操作,这些操作由主机内存模型定义。

注意

此函数不直接与设备操作同步 - 必须预先执行其他依赖于设备操作的主机同步操作,例如vkWaitForFences。因此,对于任何要对主机可见的非一致性设备写入,都必须存在以下依赖链:

  1. 设备写入

  2. 设备内存屏障,其第二个范围包括主机读取

  3. 设备上的信号(例如,栅栏信号操作

  4. 主机上的等待(例如,vkWaitForFences

  5. vkInvalidateMappedMemoryRanges

第二个同步范围包括所有在其之后发生的主机操作,这些操作由主机内存模型定义。

第一个访问范围为空。

第二个访问范围包括对指定内存范围的主机读取。

注意

当设备对内存位置的写入以这种方式对主机可见时,内存位置所在的每个完整对齐的 nonCoherentAtomSize 字节集也将变得可见,就好像它们是由设备写入的一样。例如,当 nonCoherentAtomSize 为 128 时,如果应用程序在设备上写入内存对象的第一个字节,则此命令将使内存对象的头 128 个字节可见。虽然接下来的 127 个字节的值将保持不变,但这确实算作同步的访问,因此必须小心避免数据竞争。

映射非一致性内存不会隐式地使该内存失效。

有效使用(隐式)
  • VUID-vkInvalidateMappedMemoryRanges-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkInvalidateMappedMemoryRanges-pMemoryRanges-parameter
    pMemoryRanges 必须是指向 memoryRangeCount 个有效 VkMappedMemoryRange 结构体数组的有效指针

  • VUID-vkInvalidateMappedMemoryRanges-memoryRangeCount-arraylength
    memoryRangeCount 必须大于 0

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

VkMappedMemoryRange 结构体定义如下:

// Provided by VK_VERSION_1_0
typedef struct VkMappedMemoryRange {
    VkStructureType    sType;
    const void*        pNext;
    VkDeviceMemory     memory;
    VkDeviceSize       offset;
    VkDeviceSize       size;
} VkMappedMemoryRange;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • memory 是此范围所属的内存对象。

  • offset 是从内存对象开头开始的基于零的字节偏移量。

  • size 是范围的大小,或者如果需要影响从 offset 到当前分配映射结尾的范围,则为 VK_WHOLE_SIZE

有效用法
  • VUID-VkMappedMemoryRange-memory-00684
    memory 必须当前已主机映射

  • VUID-VkMappedMemoryRange-size-00685
    如果 size 不等于 VK_WHOLE_SIZE,则 offsetsize 必须指定一个包含在 memory 的当前映射范围内的范围

  • VUID-VkMappedMemoryRange-size-00686
    如果 size 等于 VK_WHOLE_SIZE,则 offset 必须memory 的当前映射范围内

  • VUID-VkMappedMemoryRange-offset-00687
    offset 必须VkPhysicalDeviceLimits::nonCoherentAtomSize 的倍数

  • VUID-VkMappedMemoryRange-size-01389
    如果 size 等于 VK_WHOLE_SIZE,则 memory 当前映射的结尾必须要么是从内存对象的起始位置开始的 VkPhysicalDeviceLimits::nonCoherentAtomSize 字节的倍数,要么等于内存对象的结尾。

  • VUID-VkMappedMemoryRange-size-01390
    如果 size 不等于 VK_WHOLE_SIZE,则 size 必须要么是 VkPhysicalDeviceLimits::nonCoherentAtomSize 的倍数,要么 offsetsize 必须等于 memory 的大小。

有效使用(隐式)
  • VUID-VkMappedMemoryRange-sType-sType
    sType 必须VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE

  • VUID-VkMappedMemoryRange-pNext-pNext
    pNext 必须NULL

  • VUID-VkMappedMemoryRange-memory-parameter
    memory 必须是一个有效的 VkDeviceMemory 句柄。

要取消内存对象的映射,一旦应用程序不再需要对其进行主机访问,请调用

// Provided by VK_VERSION_1_0
void vkUnmapMemory(
    VkDevice                                    device,
    VkDeviceMemory                              memory);
  • device 是拥有内存的逻辑设备。

  • memory 是要取消映射的内存对象。

调用 vkUnmapMemory 等效于调用 vkUnmapMemory2,其中 pNext 链为空,flags 设置为零。

有效用法
  • VUID-vkUnmapMemory-memory-00689
    memory 必须当前已主机映射

有效使用(隐式)
  • VUID-vkUnmapMemory-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkUnmapMemory-memory-parameter
    memory 必须是一个有效的 VkDeviceMemory 句柄。

  • VUID-vkUnmapMemory-memory-parent
    memory 必须已从 device 创建、分配或检索。

主机同步
  • memory 的主机访问必须进行外部同步

或者,要取消内存对象的映射,一旦应用程序不再需要对其进行主机访问,请调用

// Provided by VK_VERSION_1_4
VkResult vkUnmapMemory2(
    VkDevice                                    device,
    const VkMemoryUnmapInfo*                    pMemoryUnmapInfo);

或等效命令

// Provided by VK_KHR_map_memory2
VkResult vkUnmapMemory2KHR(
    VkDevice                                    device,
    const VkMemoryUnmapInfo*                    pMemoryUnmapInfo);
  • device 是拥有内存的逻辑设备。

  • pMemoryUnmapInfo 是指向 VkMemoryUnmapInfo 结构的指针,该结构描述取消映射的参数。

此函数的行为与 vkUnmapMemory 完全相同,只是它通过可扩展结构指针而不是直接作为函数参数获取参数。

有效使用(隐式)
  • VUID-vkUnmapMemory2-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkUnmapMemory2-pMemoryUnmapInfo-parameter
    pMemoryUnmapInfo 必须是指向有效的 VkMemoryUnmapInfo 结构的有效指针。

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_MEMORY_MAP_FAILED

VkMemoryUnmapInfo 结构定义如下

// Provided by VK_VERSION_1_4
typedef struct VkMemoryUnmapInfo {
    VkStructureType       sType;
    const void*           pNext;
    VkMemoryUnmapFlags    flags;
    VkDeviceMemory        memory;
} VkMemoryUnmapInfo;

或等效的

// Provided by VK_KHR_map_memory2
typedef VkMemoryUnmapInfo VkMemoryUnmapInfoKHR;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • flagsVkMemoryUnmapFlagBits 的位掩码,用于指定内存映射操作的附加参数。

  • memory 是要取消映射的 VkDeviceMemory 对象。

有效用法
  • VUID-VkMemoryUnmapInfo-memory-07964
    memory 必须当前已主机映射

  • VUID-VkMemoryUnmapInfo-flags-09579
    如果在 flags 中设置了 VK_MEMORY_UNMAP_RESERVE_BIT_EXT,则必须启用 memoryUnmapReserve

  • VUID-VkMemoryUnmapInfo-flags-09580
    如果在 flags 中设置了 VK_MEMORY_UNMAP_RESERVE_BIT_EXT,则内存对象必须不是从 VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXTVK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT 的句柄类型导入的。

有效使用(隐式)
  • VUID-VkMemoryUnmapInfo-sType-sType
    sType 必须VK_STRUCTURE_TYPE_MEMORY_UNMAP_INFO

  • VUID-VkMemoryUnmapInfo-pNext-pNext
    pNext 必须NULL

  • VUID-VkMemoryUnmapInfo-flags-parameter
    flags 必须VkMemoryUnmapFlagBits 值的有效组合。

  • VUID-VkMemoryUnmapInfo-memory-parameter
    memory 必须是一个有效的 VkDeviceMemory 句柄。

主机同步
  • memory 的主机访问必须进行外部同步

可以在 VkMemoryUnmapInfo::flags 中设置的位,用于指定内存取消映射的附加属性,包括

// Provided by VK_VERSION_1_4
typedef enum VkMemoryUnmapFlagBits {
  // Provided by VK_EXT_map_memory_placed
    VK_MEMORY_UNMAP_RESERVE_BIT_EXT = 0x00000001,
} VkMemoryUnmapFlagBits;

或等效的

// Provided by VK_KHR_map_memory2
typedef VkMemoryUnmapFlagBits VkMemoryUnmapFlagBitsKHR;
  • VK_MEMORY_UNMAP_RESERVE_BIT_EXT 请求当前由内存映射占用的虚拟地址范围在 vkUnmapMemory2 调用完成后仍保持保留。未来的系统内存映射操作或对 vkMapMemoryvkMapMemory2 的调用将不会返回该范围内的地址,除非客户端之后取消保留该范围,或者通过使用 VK_MEMORY_MAP_PLACED_BIT_EXT 调用 vkMapMemory2 或执行等效的系统内存映射将映射显式放置在该范围内。当设置了 VK_MEMORY_UNMAP_RESERVE_BIT_EXT 时,内存取消映射操作可能会失败,在这种情况下,内存对象将保持主机映射状态,并且 vkUnmapMemory2 将返回 VK_ERROR_MEMORY_MAP_FAILED

// Provided by VK_VERSION_1_4
typedef VkFlags VkMemoryUnmapFlags;

或等效的

// Provided by VK_KHR_map_memory2
typedef VkMemoryUnmapFlags VkMemoryUnmapFlagsKHR;

VkMemoryUnmapFlags 是一个位掩码类型,用于设置零个或多个 VkMemoryUnmapFlagBits 的掩码。

延迟分配的内存

如果内存对象是从设置了 VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT 位的堆中分配的,则该对象的后备内存可能由实现延迟提供。内存的实际提交大小最初可能小至零(或大至请求的大小),并且随着需要额外的内存而单调递增。

仅允许将设置了此标志的内存类型绑定到使用标志包含 VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BITVkImage

对渲染过程实例完成后不需要的帧缓冲区附件使用延迟分配的内存对象可能允许某些实现从不为此类附件分配内存。

要确定当前为内存对象提交的延迟分配内存量,请调用

// Provided by VK_VERSION_1_0
void vkGetDeviceMemoryCommitment(
    VkDevice                                    device,
    VkDeviceMemory                              memory,
    VkDeviceSize*                               pCommittedMemoryInBytes);
  • device 是拥有内存的逻辑设备。

  • memory 是正在查询的内存对象。

  • pCommittedMemoryInBytes 是指向 VkDeviceSize 值的指针,成功时,其中返回当前提交的字节数。

实现可能随时更新提交,并且此查询返回的值可能已过时。

实现保证从内存对象创建时使用的内存类型指示的 heapIndex 中分配任何提交的内存。

有效用法
  • VUID-vkGetDeviceMemoryCommitment-memory-00690
    memory 必须使用报告 VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT 的内存类型创建。

有效使用(隐式)
  • VUID-vkGetDeviceMemoryCommitment-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkGetDeviceMemoryCommitment-memory-parameter
    memory 必须是一个有效的 VkDeviceMemory 句柄。

  • VUID-vkGetDeviceMemoryCommitment-pCommittedMemoryInBytes-parameter
    pCommittedMemoryInBytes 必须是指向 VkDeviceSize 值的有效指针。

  • VUID-vkGetDeviceMemoryCommitment-memory-parent
    memory 必须已从 device 创建、分配或检索。

受保护的内存

受保护的内存将设备内存划分为受保护的设备内存和未受保护的设备内存。

受保护的内存添加了以下概念:

  • 内存

    • 未受保护的设备内存,设备可以看到它,主机可以看到它

    • 受保护的设备内存,设备可以看到它,但主机不得看到它。

  • 资源

    • 未受保护的图像和未受保护的缓冲区,未受保护的内存可以绑定到这些图像和缓冲区。

    • 受保护的图像和受保护的缓冲区,受保护的内存可以绑定到这些对象。

  • 命令缓冲区

    • 非受保护的命令缓冲区,可以将其提交到设备队列以执行非受保护的队列操作。

    • 受保护的命令缓冲区,可以将其提交到支持受保护功能的设备队列以执行受保护的队列操作。

  • 设备队列

    • 非受保护的设备队列,非受保护的命令缓冲区可以提交到这些队列。

    • 支持受保护功能的设备队列,非受保护的命令缓冲区或受保护的命令缓冲区可以提交到这些队列。

  • 队列提交

    • 非受保护的队列提交,通过这种方式可以提交非受保护的命令缓冲区。

    • 受保护的队列提交,通过这种方式可以提交受保护的命令缓冲区。

  • 队列操作

    • 非受保护的队列操作

    • 受保护的队列操作

当启用protectedMemory特性时,所有管线可能会被记录在受保护或非受保护的命令缓冲区中(或者两者都记录),这在某些实现上可能会产生额外的开销。可以通过启用pipelineProtectedAccess特性来缓解这种情况。在这种情况下,使用VK_PIPELINE_CREATE_PROTECTED_ACCESS_ONLY_BIT创建的管线只能被记录在受保护的命令缓冲区中,而使用VK_PIPELINE_CREATE_NO_PROTECTED_ACCESS_BIT创建的管线只能被记录在非受保护的命令缓冲区中。

受保护内存访问规则

如果VkPhysicalDeviceProtectedMemoryProperties::protectedNoFaultVK_FALSE,则应用程序必须不执行以下任何操作

  • 在受保护的队列操作中写入非受保护的内存。

  • 在受保护的队列操作中访问受保护的内存,除非是在帧缓冲区空间管线阶段、计算着色器阶段或传输阶段。

  • 在受保护的队列操作中执行查询。

如果VkPhysicalDeviceProtectedMemoryProperties::protectedNoFaultVK_TRUE,则这些操作是有效的,但读取操作将返回未定义的值,写入操作将被丢弃或存储未定义的值。

此外,间接操作必须不在受保护的队列操作中执行。

无论这些操作是否有效,或者是否执行了任何其他无效用法,实现必须保证

  • 受保护的设备内存必须永远对主机不可见。

  • 写入非受保护的设备内存的值必须不是来自受保护内存的值的函数。

外部内存句柄类型

Android 硬件缓冲区

Android 的 NDK 定义了 AHardwareBuffer 对象,这些对象表示可在进程之间共享的设备内存,并且可以被各种媒体 API 和用于实现这些 API 的硬件访问。这些 Android 硬件缓冲区对象可以被导入到 VkDeviceMemory 对象中,以便通过 Vulkan 访问,或者从 Vulkan 导出。如果 VkImageVkBuffer 是使用 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID 创建的,则可以将其绑定到导入或导出的 VkDeviceMemory 对象。

为了消除不必要的编译时依赖,Vulkan 头部提供了一个不完整的 AHardwareBuffer 类型定义。

// Provided by VK_ANDROID_external_memory_android_hardware_buffer
struct AHardwareBuffer;

实际的 AHardwareBuffer 类型定义在 Android NDK 头部中。

可以使用 AHardwareBuffer_describe 函数获取 AHardwareBuffer 对象的 NDK 格式、用法和大小/尺寸。虽然 Android 硬件缓冲区可以在不使用该函数的情况下导入到 Vulkan 或从 Vulkan 导出,但有效的用法和实现行为是根据它返回的 AHardwareBuffer_Desc 属性定义的。

Android 硬件缓冲区对象使用 Android NDK 函数进行引用计数,这超出了本规范的范围。从 Android 硬件缓冲区导入的或者可以导出到 Android 硬件缓冲区的 VkDeviceMemory 必须获取其 AHardwareBuffer 对象的引用,并且必须在释放设备内存时释放此引用。在 Vulkan 命令的主机执行期间(该命令以 Android 硬件缓冲区作为参数,包括通过 pNext 链的间接参数),应用程序必须不将 Android 硬件缓冲区的引用计数减至零。

可以使用 NDK 函数映射和取消映射 Android 硬件缓冲区以进行 CPU 访问。这些锁定和解锁 API 被认为获取和释放了 Android 硬件缓冲区的所有权,应用程序必须遵循 外部资源共享 中描述的规则,以在 Vulkan 实例和这些原生 API 之间传输所有权。

Android 硬件缓冲区可以与同一设备上的外部 API 和 Vulkan 实例以及与外部设备共享。在传输 Android 硬件缓冲区的所有权时,队列族所有权转移中描述的外部和外部特殊队列族并不相同。所有生成或使用 Android 硬件缓冲区的 API 都被认为使用外部设备,但具有匹配的设备和驱动程序 UUID 的 OpenGL ES 上下文和 Vulkan 逻辑设备除外。当 Android 硬件缓冲区的用法仅允许在同一物理设备上使用时,实现可能将与外部队列族之间的传输视为与外部队列族之间的传输。

Android 硬件缓冲区的最佳用法

Vulkan 缓冲区和图像用法标志与 Android 硬件缓冲区用法标志不完全对应。当使用非 Vulkan API 分配 Android 硬件缓冲区时,如果包含任何 AHARDWAREBUFFER_USAGE_GPU_* 用法位,则默认情况下,分配器必须以这样一种方式分配内存,使其支持用法等效表中没有 Android 硬件缓冲区等效项的 Vulkan 用法和创建标志。

可以将 VkAndroidHardwareBufferUsageANDROID 结构包含在传递给 vkGetPhysicalDeviceImageFormatProperties2VkImageFormatProperties2 结构的 pNext 链中,以获取特定 Vulkan 资源创建参数的最佳 Android 硬件缓冲区用法标志。这些命令返回的一些用法标志是基于输入参数必需的,但也可能返回其他供应商特定的用法标志 (AHARDWAREBUFFER_USAGE_VENDOR_*)。任何使用这些供应商特定的用法标志分配并导入到 Vulkan 的 Android 硬件缓冲区必须仅绑定到使用参数创建的资源,这些参数是用于获取 Android 硬件缓冲区用法的参数的子集,因为内存可能以不兼容其他参数的方式分配。如果一个 Android 硬件缓冲区在推荐的用法之外,还成功地分配了额外的非供应商特定的用法标志,那么它必须支持以与仅使用推荐的用法分配的 Android 硬件缓冲区相同的方式使用,以及以额外的用法指示的方式使用。

Android 硬件缓冲区外部格式

Android 硬件缓冲区可能使用特定于实现的格式、布局、颜色模型等表示图像,这些格式、布局、颜色模型等没有 Vulkan 等效项。这种外部格式通常被外部图像源(如视频解码器或摄像头)使用。Vulkan 可以导入具有外部格式的 Android 硬件缓冲区,但由于图像内容可能采用专有表示形式,因此具有外部格式的图像必须具有最佳平铺,并且它们的使用受到限制。具有外部格式的图像必须仅使用启用了 Y′CBCR 转换的采样器进行采样。

将由 Android 硬件缓冲区支持的图像可以通过将 VkImageCreateInfo::format 设置为 VK_FORMAT_UNDEFINED,并在 pNext 链中包含 VkExternalFormatANDROID 结构来使用外部格式。即使 Android 硬件缓冲区具有 等效 Vulkan 格式的格式,也可以使用外部格式创建图像,以便一致地处理可能使用这两种格式的图像源。但是,所有使用外部格式创建的图像都必须遵守与外部格式相关的有效使用要求,即使 Android 硬件缓冲区的格式具有 Vulkan 等效项。Android 硬件缓冲区的外部格式可以通过将 VkAndroidHardwareBufferFormatPropertiesANDROID 结构传递给 vkGetAndroidHardwareBufferPropertiesANDROID 来获得。

Android 硬件缓冲区图像资源

Android 硬件缓冲区具有固有的宽度、高度、格式和使用属性,因此绑定到从 Android 硬件缓冲区导入的内存的 Vulkan 图像必须使用专用分配:对于使用包含 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROIDVkExternalMemoryImageCreateInfo::handleTypes 创建的图像,VkMemoryDedicatedRequirements::requiresDedicatedAllocation 必须VK_TRUE。在创建将绑定到导入的 Android 硬件缓冲区的图像时,图像创建参数必须等效于 VkMemoryAllocateInfo 的有效使用所描述的 AHardwareBuffer 属性。类似地,为专用图像分配的设备内存必须在绑定到该图像之前,才能导出到 Android 硬件缓冲区,并且实现必须返回一个属性从该图像导出的 Android 硬件缓冲区

对于具有 Android 硬件缓冲区外部句柄类型的图像,实现可能支持比非外部图像更少的图像创建参数组合。可以通过将 VkExternalImageFormatProperties 传递给 vkGetPhysicalDeviceImageFormatProperties2,并将 handleType 设置为 VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID 来确定对给定参数集的支持。任何在 Vulkan 之外成功分配的,且使用包括 AHARDWAREBUFFER_USAGE_GPU_* 的 Android 硬件缓冲区,当使用等效的 Vulkan 图像参数时必须支持。如果支持导入给定的图像参数选择,则它们也可以用于创建将导出到 Android 硬件缓冲区的图像和内存。

表 1. AHardwareBuffer 格式等效性
AHardwareBuffer 格式 Vulkan 格式

AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM

VK_FORMAT_R8G8B8A8_UNORM

AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM 1

VK_FORMAT_R8G8B8A8_UNORM

AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM

VK_FORMAT_R8G8B8_UNORM

AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM

VK_FORMAT_R5G6B5_UNORM_PACK16

AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT

VK_FORMAT_R16G16B16A16_SFLOAT

AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM

VK_FORMAT_A2B10G10R10_UNORM_PACK32

AHARDWAREBUFFER_FORMAT_D16_UNORM

VK_FORMAT_D16_UNORM

AHARDWAREBUFFER_FORMAT_D24_UNORM

VK_FORMAT_X8_D24_UNORM_PACK32

AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT

VK_FORMAT_D24_UNORM_S8_UINT

AHARDWAREBUFFER_FORMAT_D32_FLOAT

VK_FORMAT_D32_SFLOAT

AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT

VK_FORMAT_D32_SFLOAT_S8_UINT

AHARDWAREBUFFER_FORMAT_S8_UINT

VK_FORMAT_S8_UINT

表 2. AHardwareBuffer 使用等效性
AHardwareBuffer 使用 Vulkan 使用或创建标志

VK_IMAGE_USAGE_TRANSFER_SRC_BIT

VK_IMAGE_USAGE_TRANSFER_DST_BIT

AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE

VK_IMAGE_USAGE_SAMPLED_BIT

AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE

VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT

AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER 3

VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT

AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER 3

VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT

AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP

VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT

AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE

2

AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT

VK_IMAGE_CREATE_PROTECTED_BIT

VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT

VK_IMAGE_CREATE_EXTENDED_USAGE_BIT

AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER 4

VK_IMAGE_USAGE_STORAGE_BIT

1

Vulkan 不区分 AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORMAHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:它们都表现为 VK_FORMAT_R8G8B8A8_UNORM。在外部实体写入 AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM Android 硬件缓冲区后,Vulkan 从 X/A 分量读取的值是未定义的。为了模拟采样或混合期间 X 分量的传统行为,应用程序应该在图像视图分量映射中使用 VK_COMPONENT_SWIZZLE_ONE,并在颜色混合因子中使用 VK_BLEND_FACTOR_ONE。当从此类图像复制到另一个图像或缓冲区时,无法避免复制这些未定义的值。

2

AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE 标志不对应于 Vulkan 图像使用或创建标志。相反,它的存在表示 Android 硬件缓冲区包含完整的 mipmap 链,它的不存在表示 Android 硬件缓冲区仅包含单个 mip 级别。

3

只有对格式有效的图像使用才是有效的。获取一个具有 AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM 格式和 AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER 使用的 Android 硬件缓冲区,并尝试创建具有 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT 的图像是无效的。

4

BLOB 以外的硬件缓冲区格式结合使用。

当将 VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT 与 Android 硬件缓冲区图像一起使用时,应用程序应该使用 VkImageFormatListCreateInfo 来通知实现将使用哪些视图格式与图像一起使用。对于一些常见的格式集,这允许某些实现在通过 Vulkan 访问图像时提供明显更好的性能。

Android 硬件缓冲区资源

格式为 AHARDWAREBUFFER_FORMAT_BLOB 且用法包含 AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER 的 Android 硬件缓冲区可以用作 VkBuffer 对象的后备存储。此类 Android 硬件缓冲区的字节大小由其 width 指定;heightlayers 均为 1

与图像不同,由 Android 硬件缓冲区支持的缓冲区资源不需要专用分配。

导出的 AHardwareBuffer 对象如果没有专用图像,则必须具有 AHARDWAREBUFFER_FORMAT_BLOB 格式,用法必须包含 AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFERwidth 必须等于设备内存分配大小,heightlayers 必须1

QNX 屏幕缓冲区

QNX SDP 定义了 _screen_buffer 对象,该对象表示 QNX 屏幕图形子系统可以直接在其窗口系统 API 中使用的缓冲区。更具体地说,屏幕缓冲区是存储像素数据的内存区域。它可以附加到屏幕窗口、流或像素图。这些 QNX 屏幕缓冲区对象可以导入到 VkDeviceMemory 对象中,以便通过 Vulkan 访问。如果 VkImageVkBuffer 是使用 VK_EXTERNAL_MEMORY_HANDLE_TYPE_SCREEN_BUFFER_BIT_QNX 创建的,则可以将其绑定到导入的 VkDeviceMemory 对象。

struct _screen_buffer 是强类型的,因此命名句柄类型是多余的。struct _screen_buffer 图像的内部布局以及大小可能取决于本地用法标志,这些标志没有相应的 Vulkan 对等项。

QNX 屏幕缓冲区有效性

QNX SDP 中屏幕的设计使得难以从屏幕外部确定对象的有效性。因此,应用程序必须确保在各种 Vulkan 接口中提供的 QNX 屏幕缓冲区对象是使用 QNX 屏幕 API 显式创建的。有关更多信息,请参阅 QNX SDP 文档。

从 QNX 屏幕缓冲区导入的 VkDeviceMemory 无法获取对其 _screen_buffer 对象的引用。因此,在主机执行 Vulkan 命令时,如果 Vulkan 命令将 QNX 屏幕缓冲区作为参数(包括通过 pNext 链的间接参数),应用程序必须确保 QNX 屏幕缓冲区资源保持有效。

通常,为了使 _screen_buffer 对象在 Vulkan 实现中有效使用,该缓冲区对象应该具有 _screen_buffer::SCREEN_PROPERTY_USAGE,其中至少包含以下之一:SCREEN_USAGE_VULKANSCREEN_USAGE_OPENGL_ES2SCREEN_USAGE_OPENGL_ES3SCREEN_USAGE_NATIVE。所需的具体屏幕原生用法标志取决于 Vulkan 实现,QNX 屏幕本身不一定会强制执行这些要求。请注意,屏幕原生用法标志与 Vulkan 规范中的用法标志无关。

QNX 屏幕缓冲区外部格式

QNX 屏幕缓冲区可以使用特定于实现的格式、布局、颜色模型等表示图像,这些格式、布局、颜色模型等没有 Vulkan 等效项。此类外部格式通常由外部图像源(如视频解码器或摄像头)使用。Vulkan 可以导入具有外部格式的 QNX 屏幕缓冲区,但由于图像内容采用无法发现且可能专有的表示形式,因此具有外部格式的图像必须仅用作采样图像,必须仅使用启用了 Y′CBCR 转换的采样器进行采样,并且必须具有最佳平铺。

将由 QNX 屏幕缓冲区支持的图像可以通过将 VkImageCreateInfo::format 设置为 VK_FORMAT_UNDEFINED 并将 VkExternalFormatQNX 结构包含在 pNext 链中来使用外部格式。即使 QNX 屏幕缓冲区的格式具有 等效的 Vulkan 格式,也可以创建具有外部格式的图像,以实现对可能使用任一类别格式的源的图像的一致处理。QNX 屏幕缓冲区的外部格式可以通过将 VkScreenBufferFormatPropertiesQNX 结构传递给 vkGetScreenBufferPropertiesQNX 来获取。

QNX 屏幕缓冲区图像资源

QNX 屏幕缓冲区具有内在的宽度、高度、格式和用法属性,因此绑定到从 QNX 屏幕缓冲区导入的内存的 Vulkan 图像必须使用专用分配:对于使用包含 VK_EXTERNAL_MEMORY_HANDLE_TYPE_SCREEN_BUFFER_BIT_QNXVkExternalMemoryImageCreateInfo::handleTypes 创建的图像,VkMemoryDedicatedRequirements::requiresDedicatedAllocation 必须VK_TRUE。创建将绑定到导入的 QNX 屏幕缓冲区的图像时,图像创建参数必须等效于 VkMemoryAllocateInfo 的有效用法中所述的 _screen_buffer 属性。

表 3. QNX 屏幕缓冲区格式等效性
QNX 屏幕格式 Vulkan 格式

SCREEN_FORMAT_RGBA8888

VK_FORMAT_B8G8R8A8_UNORM

SCREEN_FORMAT_RGBX8888 1

VK_FORMAT_B8G8R8A8_UNORM

SCREEN_FORMAT_BGRA8888

VK_FORMAT_R8G8B8A8_UNORM

SCREEN_FORMAT_BGRX8888 1

VK_FORMAT_R8G8B8A8_UNORM

SCREEN_FORMAT_RGBA1010102

VK_FORMAT_A2R10G10B10_UNORM_PACK32

SCREEN_FORMAT_RGBX1010102 1

VK_FORMAT_A2R10G10B10_UNORM_PACK32

SCREEN_FORMAT_BGRA1010102

VK_FORMAT_A2B10G10R10_UNORM_PACK32

SCREEN_FORMAT_BGRX1010102 1

VK_FORMAT_A2B10G10R10_UNORM_PACK32

SCREEN_FORMAT_RGBA5551

VK_FORMAT_A1R5G5B5_UNORM_PACK16

SCREEN_FORMAT_RGBX5551 1

VK_FORMAT_A1R5G5B5_UNORM_PACK16

SCREEN_FORMAT_RGB565

VK_FORMAT_R5G6B5_UNORM_PACK16

SCREEN_FORMAT_RGB888

VK_FORMAT_R8G8B8_UNORM

1

Vulkan 不区分 SCREEN_FORMAT_RGBA8888SCREEN_FORMAT_RGBX8888:它们的行为都类似于 VK_FORMAT_R8G8B8A8_UNORM。在外部实体写入 SCREEN_FORMAT_RGBX8888 QNX 屏幕缓冲区后,Vulkan 从 X/A 组件读取的值是未定义的。为了在采样或混合过程中模拟 X 组件的传统行为,应用程序应该在图像视图组件映射中使用 VK_COMPONENT_SWIZZLE_ONE,在颜色混合因子中使用 VK_BLEND_FACTOR_ONE。从这样的图像复制到另一个图像或缓冲区时,无法避免复制这些未定义的值。相同的行为适用于以下几对:SCREEN_FORMAT_BGRA8888SCREEN_FORMAT_BGRX8888SCREEN_FORMAT_RGBA1010102SCREEN_FORMAT_RGBX1010102SCREEN_FORMAT_BGRA1010102SCREEN_FORMAT_BGRX1010102SCREEN_FORMAT_RGBA5551SCREEN_FORMAT_RGBX5551

对等内存功能

对等内存是为给定的物理设备分配的内存,然后绑定到资源,并由逻辑设备中表示多个物理设备的不同物理设备访问。设备可能不支持某些读取和写入对等内存的方式。

要确定如何访问对等内存,请调用

// Provided by VK_VERSION_1_1
void vkGetDeviceGroupPeerMemoryFeatures(
    VkDevice                                    device,
    uint32_t                                    heapIndex,
    uint32_t                                    localDeviceIndex,
    uint32_t                                    remoteDeviceIndex,
    VkPeerMemoryFeatureFlags*                   pPeerMemoryFeatures);

或等效命令

// Provided by VK_KHR_device_group
void vkGetDeviceGroupPeerMemoryFeaturesKHR(
    VkDevice                                    device,
    uint32_t                                    heapIndex,
    uint32_t                                    localDeviceIndex,
    uint32_t                                    remoteDeviceIndex,
    VkPeerMemoryFeatureFlags*                   pPeerMemoryFeatures);
  • device 是拥有内存的逻辑设备。

  • heapIndex 是内存堆的索引,从中分配内存。

  • localDeviceIndex 是执行内存访问的物理设备的设备索引。

  • remoteDeviceIndex 是为之分配内存的物理设备的设备索引。

  • pPeerMemoryFeatures 是指向 VkPeerMemoryFeatureFlags 位掩码的指针,该位掩码指示对于堆、本地和远程设备的组合支持哪些类型的内存访问。

有效用法
  • VUID-vkGetDeviceGroupPeerMemoryFeatures-heapIndex-00691
    heapIndex 必须 小于 memoryHeapCount

  • VUID-vkGetDeviceGroupPeerMemoryFeatures-localDeviceIndex-00692
    localDeviceIndex 必须 是有效的设备索引

  • VUID-vkGetDeviceGroupPeerMemoryFeatures-remoteDeviceIndex-00693
    remoteDeviceIndex 必须 是有效的设备索引

  • VUID-vkGetDeviceGroupPeerMemoryFeatures-localDeviceIndex-00694
    localDeviceIndex 必须 不等于 remoteDeviceIndex

有效使用(隐式)
  • VUID-vkGetDeviceGroupPeerMemoryFeatures-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkGetDeviceGroupPeerMemoryFeatures-pPeerMemoryFeatures-parameter
    pPeerMemoryFeatures 必须 是指向 VkPeerMemoryFeatureFlags 值的有效指针

vkGetDeviceGroupPeerMemoryFeatures::pPeerMemoryFeatures可能设置的位,指示支持的对等内存特性,是

// Provided by VK_VERSION_1_1
typedef enum VkPeerMemoryFeatureFlagBits {
    VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT = 0x00000001,
    VK_PEER_MEMORY_FEATURE_COPY_DST_BIT = 0x00000002,
    VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT = 0x00000004,
    VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT = 0x00000008,
  // Provided by VK_KHR_device_group
    VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT_KHR = VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT,
  // Provided by VK_KHR_device_group
    VK_PEER_MEMORY_FEATURE_COPY_DST_BIT_KHR = VK_PEER_MEMORY_FEATURE_COPY_DST_BIT,
  // Provided by VK_KHR_device_group
    VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT_KHR = VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT,
  // Provided by VK_KHR_device_group
    VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT_KHR = VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT,
} VkPeerMemoryFeatureFlagBits;

或等效的

// Provided by VK_KHR_device_group
typedef VkPeerMemoryFeatureFlagBits VkPeerMemoryFeatureFlagBitsKHR;
  • VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT 指定内存可以作为任何 vkCmdCopy* 命令的源进行访问。

  • VK_PEER_MEMORY_FEATURE_COPY_DST_BIT 指定内存可以作为任何 vkCmdCopy* 命令的目标进行访问。

  • VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT 指定内存可以作为任何内存访问类型进行读取。

  • VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT 指定内存可以作为任何内存访问类型进行写入。着色器原子操作被认为是写入。

内存堆的对等内存特性也适用于在图像布局转换期间可能执行的任何访问。

对于所有主机本地堆和至少一个设备本地内存堆,必须支持VK_PEER_MEMORY_FEATURE_COPY_DST_BIT

如果设备不支持对等内存特性,只要实际只访问本地绑定,使用包含本地和对等内存绑定的资源以及相应的访问类型仍然有效。 例如,执行分帧渲染的应用程序会使用包含本地和对等内存绑定的帧缓冲区附件,但会裁剪渲染以仅更新本地内存。

// Provided by VK_VERSION_1_1
typedef VkFlags VkPeerMemoryFeatureFlags;

或等效的

// Provided by VK_KHR_device_group
typedef VkPeerMemoryFeatureFlags VkPeerMemoryFeatureFlagsKHR;

VkPeerMemoryFeatureFlags 是一种位掩码类型,用于设置零个或多个 VkPeerMemoryFeatureFlagBits 的掩码。

不透明捕获地址查询

要从内存对象查询 64 位不透明捕获地址值,请调用

// Provided by VK_VERSION_1_2
uint64_t vkGetDeviceMemoryOpaqueCaptureAddress(
    VkDevice                                    device,
    const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo);

或等效命令

// Provided by VK_KHR_buffer_device_address
uint64_t vkGetDeviceMemoryOpaqueCaptureAddressKHR(
    VkDevice                                    device,
    const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo);

64 位返回值是一个不透明地址,表示 pInfo->memory 的起始位置。

如果内存对象使用非零值的 VkMemoryOpaqueCaptureAddressAllocateInfo::opaqueCaptureAddress 分配,则返回值必须是相同的地址。

这些不透明地址的预期用途仅供跟踪捕获/重放工具在跟踪中存储这些地址,并在重放期间随后指定它们。

有效用法
有效使用(隐式)
  • VUID-vkGetDeviceMemoryOpaqueCaptureAddress-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkGetDeviceMemoryOpaqueCaptureAddress-pInfo-parameter
    pInfo 必须 是指向有效 VkDeviceMemoryOpaqueCaptureAddressInfo 结构的有效指针

VkDeviceMemoryOpaqueCaptureAddressInfo 结构的定义如下

// Provided by VK_VERSION_1_2
typedef struct VkDeviceMemoryOpaqueCaptureAddressInfo {
    VkStructureType    sType;
    const void*        pNext;
    VkDeviceMemory     memory;
} VkDeviceMemoryOpaqueCaptureAddressInfo;

或等效的

// Provided by VK_KHR_buffer_device_address
typedef VkDeviceMemoryOpaqueCaptureAddressInfo VkDeviceMemoryOpaqueCaptureAddressInfoKHR;
  • sType 是标识此结构的 VkStructureType 值。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • memory 指定正在查询地址的内存。

有效用法
  • VUID-VkDeviceMemoryOpaqueCaptureAddressInfo-memory-03336
    memory 必须已使用 VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT 分配

有效使用(隐式)
  • VUID-VkDeviceMemoryOpaqueCaptureAddressInfo-sType-sType
    sType 必须VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO

  • VUID-VkDeviceMemoryOpaqueCaptureAddressInfo-pNext-pNext
    pNext 必须NULL

  • VUID-VkDeviceMemoryOpaqueCaptureAddressInfo-memory-parameter
    memory 必须是一个有效的 VkDeviceMemory 句柄。