Vulkan Specification(Vulkan规范):第十章 10.1 主机内存

Vulkan 内存分为两类: 主机内存 和 设备内存 。

10.1. 主机内存

主机内存是Vulkan实现需要的、设备不可见的内存。 这些内存可以用来存储软件内部数据。

Vulkan给应用程序提供了代表Vulkan实现来操作主机内存分配的机会。 如果这个特征没有被使用,Vulkan实现将使用自己的内存分配函数。 因为大多数内存分配都不是在要求高性能代码区域的,这就不是一个提升性能的特征了。 相反,在一些嵌入式的平台上,这还是非常有用的,如为了调试(e.g. putting a guard page after all host allocations), 或者记录内存分配。

内存分配器是应用程序通过一个指向VkAllocationCallbacks类型数据的指针来提供的。

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 是一个指向应用程序定义的函数的指针,当被Vulkan实现调用时,就进行内部内存分配,类型为 PFN_vkInternalAllocationNotification

  • pfnInternalFree 是一个指向应用程序定义的函数的指针,当被Vulkan实现调用时,就释放内部内存,类型为PFN_vkInternalFreeNotification

正确使用

  • pfnAllocation 必须: 是一个有效的用户自定义的PFN_vkAllocationFunction 类型的函数指针。

  • pfnReallocation 必须: 是一个指向有效的用户自定义的 PFN_vkReallocationFunction类型的函数指针。

  • pfnFree 必须: 是一个指向有效的用户自定义的PFN_vkFreeFunction类型指针。

  • 如果 pfnInternalAllocation 或者 pfnInternalFree 不为 NULL,那么两个都必须: 是有效的回调函数。

pfnAllocation定义如下:

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`,且如果Vulkan实现因为没有获取要求的内存而不能正确的继续处理当前命令时, Vulkan实现必须把这个当作是运行时错误,在合适的时候给发生这个状况的命令产生一个VK_ERROR_OUT_OF_HOST_MEMORY错误, 如Return Codes中所描述。

如果Vulkan实现在没有获取到要求分配的内存时能够继续正确的处理当前命令,那么它不能 因这次内存分配失败而产生VK_ERROR_OUT_OF_HOST_MEMORY

pfnReallocation类型如下:

typedef void* (VKAPI_PTR *PFN_vkReallocationFunction)(
    void*                                       pUserData,
    void*                                       pOriginal,
    size_t                                      size,
    size_t                                      alignment,
    VkSystemAllocationScope                     allocationScope);
  • pUserData 是由应用程序指定的内存分配器的VkAllocationCallbacks::pUserData 指定的。

  • pOriginal 必须: 是 NULL 或者是 同一个内存分配器的pfnReallocation 或者 pfnAllocation 返回的指针。

  • size 是要求分配的内存字节大小。

  • alignment 是内存分配器要求的内存对齐的大小,以字节为单位,必须是2的幂。

  • allocationScope 是一个 VkSystemAllocationScope 类型的值,指定了内存分配的生命周期,如 这里所述。

pfnReallocation必须: 返回size 字节的内存,原内存的内容从zero 到 min(original size, new size) - 1 必须: 被保留在新分配的内存中。 如果 size比原来的内存要大, 附加部分内存的内容是未定义的。 如果满足这些创建新内存的条件,那么原来分配的内存应被释放掉了。

若 pOriginal 是 NULL, 那么 pfnReallocation 必须: 表现的和以相同参数(除了pOriginal)调用PFN_vkAllocationFunction 表现完全相同。

若 size 为0, 那么 pfnReallocation 必须: 表现的和以相同参数pUserDatapMemory 等同于pOriginal来调用 PFN_vkFreeFunction 完全相同。

若 pOriginal 是 non-NULL, Vulkan实现必须 必须: 保证 alignment 等于 分配pOriginal时所用到的alignment

若这个函数调用失败,pOriginal 是 non-NULL,应用程序不能: 释放掉原来的内存。

pfnReallocation 必须: 符合PFN_vkAllocationFunction返回值的规则

pfnFree 类型定义如下:

typedef void (VKAPI_PTR *PFN_vkFreeFunction)(
    void*                                       pUserData,
    void*                                       pMemory);
  • pUserData 是由应用程序指定的内存分配器的VkAllocationCallbacks::pUserData 指定的。

  • pMemory 是需要被释放的内存。

pMemory 可能: 是 NULL, 此时回调函数 必须: 谨慎的处理。 若 pMemory 是 non-NULL, 它必须: 是一个指针,指向 pfnAllocation 或 pfnReallocation之前分配的内存。 应用程序 应该: 释放此内存。

pfnInternalAllocation 类型定义如下:

typedef void (VKAPI_PTR *PFN_vkInternalAllocationNotification)(
    void*                                       pUserData,
    size_t                                      size,
    VkInternalAllocationType                    allocationType,
    VkSystemAllocationScope                     allocationScope);
  • pUserData 是由应用程序指定的内存分配器的VkAllocationCallbacks::pUserData 指定的。

  • size 是要求分配的内存字节大小。

  • allocationType 是要求的内存分配的类型。

  • allocationScope 是一个 VkSystemAllocationScope 类型的值,指定了内存分配的生命周期,如 这里所述。

这是一个纯粹的查看信息的回调函数。

pfnInternalFree定义如下:

typedef void (VKAPI_PTR *PFN_vkInternalFreeNotification)(
    void*                                       pUserData,
    size_t                                      size,
    VkInternalAllocationType                    allocationType,
    VkSystemAllocationScope                     allocationScope);
  • pUserData 是由应用程序指定的内存分配器的VkAllocationCallbacks::pUserData 指定的。

  • size 是要求分配的内存字节大小。

  • allocationType 是要求的内存分配的类型。

  • allocationScope 是一个 VkSystemAllocationScope 类型的值,指定了内存分配的生命周期,如 这里所述。

每一份分配的内存都有 分配存活期 ,定义了它自己的生命周期和所关联对象。 内存存活期是通过传递给VkAllocationCallbacks中定义的回调函数的allocationScope 参数提供的。 VkSystemAllocationScope 定义的可选的值如下:

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 - The allocation is scoped to the duration of the Vulkan command.

  • VK_SYSTEM_ALLOCATION_SCOPE_OBJECT - The allocation is scoped to the lifetime of the Vulkan object that is being created or used.

  • VK_SYSTEM_ALLOCATION_SCOPE_CACHE - The allocation is scoped to the lifetime of a VkPipelineCache object.

  • VK_SYSTEM_ALLOCATION_SCOPE_DEVICE - The allocation is scoped to the lifetime of the Vulkan device.

  • VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE - The allocation is scoped to the lifetime of the Vulkan instance.

大多数Vulkan命令操作单个对象,或者创建、操控单一对象。当一份分配的内存使用 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT 或 VK_SYSTEM_ALLOCATION_SCOPE_CACHE时,内存的存活范围就是被创建或操控的对象。

当Vulkan实现获取主机端内存时,它将回调应用程序提供的回调函数来使用特定的内存分配器和内存存活范围:

  • 若分配的内存生存周期限定于一个命令之内,内存分配器将使用 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND。 若创建的、或者被操控的对象有对应的内存分配器,那么将使用该特定的内存分配器,否则若 父 VkDevice 有内存分配器,便使用此内存分配器,否则便使用父 VkInstance 拥有的内存分配器。

  • 若 If an allocation is associated with an object of type VkPipelineCache, the allocator will use the VK_SYSTEM_ALLOCATION_SCOPE_CACHE allocation scope. The most specific allocator available is used (pipeline cache, else device, else instance). Else,

  • If an allocation is scoped to the lifetime of an object, that object is being created or manipulated by the command, and that object’s type is not VkDevice or VkInstance, the allocator will use an allocation scope of VK_SYSTEM_ALLOCATION_SCOPE_OBJECT. The most specific allocator available is used (object, else device, else instance). Else,

  • If an allocation is scoped to the lifetime of a device, the allocator will use an allocation scope of VK_SYSTEM_ALLOCATION_SCOPE_DEVICE. The most specific allocator available is used (device, else instance). Else,

  • If the allocation is scoped to the lifetime of an instance and the instance has an allocator, its allocator will be used with an allocation scope of VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE.

  • Otherwise an implementation will allocate memory through an alternative mechanism that is unspecified.

从缓存池中分配出来的对象并没有指定它们对应的内存分配器。 当Vulkan实现为此对象获取主机端内存时,内存是由父缓存池的内存分配器获取的。

不应期待应用程序会负责主机端执行代码时处理内存分配活动,因为多平台上Vulkan实现的负责的安全性问题。 Vulkan实现将在内部分配内存,当这些内存分配或释放时,调用通知性的回调函数告诉应用程序。 当分配这些可执行的内存时,pfnInternalAllocation 将会被调用。 当释放这些可执行的内存时,pfnInternalFree 将被调用。 当分配或释放这些可执行的内存时,Vulkan实现将只调用通知性的回调函数。

传递给 pfnInternalAllocation 和pfnInternalFree 函数的allocationType 参数 可能: 是如下值:

typedef enum VkInternalAllocationType {
    VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE = 0,
} VkInternalAllocationType;
  • VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE - 分配的内存是计划给CPU端使用的。

Vulkan实现在API命令执行期间,只能调用应用程序在当前线程提供的分配函数。 Vulkan实现不应该同时调用这些回调函数。如果需要保持同步,回调函数应该自己实现。提供信息这一类的回调函数也和内存分配函数一样遵从此限制。

若Vulkan实现倾向于在vkCreate*命令返回和对应的 vkDestroy*命令开始之间通过VkAllocationCallbacks 数据结构来进行函数调用,该Vulkan实现必须在vkCreate*返回之前保存一份内存分配器的copy。 它们依赖的回掉函数和任何数据结构都必须在与之关联的对象生命周期内都保持有效。

若给vkCreate*提供一个内存分配器,则必须要给对应的vkDestroy*命令提供一个兼容匹配的内存分配器。 若用pfnAllocation or pfnReallocation分配而来的内存都可以被pfnReallocation or pfnFree释放掉,那么两个VkAllocationCallbacks 数据结构必须兼容。 An allocator must not be provided to a vkDestroy* command if an allocator was not provided to the corresponding vkCreate* command.

If a non-NULL allocator is used, the pfnAllocationpfnReallocation and pfnFree members must be non-NULL and point to valid implementations of the callbacks. An application can choose to not provide informational callbacks by setting both pfnInternalAllocation and pfnInternalFree to NULLpfnInternalAllocation and pfnInternalFree must either both be NULL or both be non-NULL.

If pfnAllocation or pfnReallocation fail, the implementation may fail object creation and/or generate an VK_ERROR_OUT_OF_HOST_MEMORY error, as appropriate.

内存分配回调函数不能调用任何Vulkan命令。

The following sets of rules define when an implementation is permitted to call the allocator callbacks.

pfnAllocation 或者 pfnReallocation 可能在一下情形中被调用:

  • Allocations scoped to a VkDevice or VkInstance may be allocated from any API command.

  • Allocations scoped to a command may be allocated from any API command.

  • Allocations scoped to a VkPipelineCache may only be allocated from:

    • vkCreatePipelineCache

    • vkMergePipelineCaches for dstCache

    • vkCreateGraphicsPipelines for pPipelineCache

    • vkCreateComputePipelines for pPipelineCache

  • Allocations scoped to a VkDescriptorPool may only be allocated from:

    • any command that takes the pool as a direct argument

    • vkAllocateDescriptorSets for the descriptorPool member of its pAllocateInfo parameter

    • vkCreateDescriptorPool

  • Allocations scoped to a VkCommandPool may only be allocated from:

    • any command that takes the pool as a direct argument

    • vkCreateCommandPool

    • vkAllocateCommandBuffers for the commandPool member of its pAllocateInfo parameter

    • any vkCmd* command whose commandBuffer was allocated from that VkCommandPool

  • Allocations scoped to any other object may only be allocated in that object’s vkCreate* command.

pfnFree 可能在一下情形中被调用:

  • Allocations scoped to a VkDevice or VkInstance may be freed from any API command.

  • Allocations scoped to a command must be freed by any API command which allocates such memory.

  • Allocations scoped to a VkPipelineCache may be freed from vkDestroyPipelineCache.

  • Allocations scoped to a VkDescriptorPool may be freed from

    • any command that takes the pool as a direct argument

  • Allocations scoped to a VkCommandPool may be freed from:

    • any command that takes the pool as a direct argument

    • vkResetCommandBuffer whose commandBuffer was allocated from that VkCommandPool

  • Allocations scoped to any other object may be freed in that object’s vkDestroy* command.

  • Any command that allocates host memory may also free host memory of the same scope.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值