Vulkan Specification(Vulkan规范):第十章 10.2.1

10.2.1. CPU访问设备内存对象

通过vkAllocateMemory创建的内存对象不能被CPU端直接访问。

创建时带有VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT属性的内存对象被认为是 可映射的 。 内存对象必须是可映射的,才能被映射到CPU端。

可调用如下命令可以获取指向映射到可映射内存对象的指针:

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

  • memory 是将要被映射的VkDeviceMemory 对象。

  • offset 是一个从内存对象的起始的 从0开始的字节offset。

  • size 是需要映射的内存区间的大小,或者值为 VK_WHOLE_SIZE时表示 从 offset 到分配的内存结尾的全部映射。

  • flags 被保留。

  • ppData 指向一个 被返回的 host-accessible指向 被映射的区间指针。 这个指针 减去 offset 必须被按照 VkPhysicalDeviceLimits::minMemoryMapAlignment 对齐。

若调用 vkMapMemory对已映射过的内存对象再次映射,则是应用程序的错误。

 

注意

vkMapMemory will fail if the implementation is unable to allocate an appropriately sized contiguous virtual address range, e.g. due to virtual address space fragmentation or platform limits. In such cases, vkMapMemory must return VK_ERROR_MEMORY_MAP_FAILED. The application can improve the likelihood of success by reducing the size of the mapped range and/or removing unneeded mappings using VkUnmapMemory.

vkMapMemory 并不在返回一个host端可访问的指针之前检查设备内存当前是否正在使用中。 应用程序必须保证之前提交的任何命令(会向该区间写入的命令)已经在host端读取或者写入完成,且任何之前被提交的命令(从该区间读取内容的命令) 在host端写入之前已经完成。 (参看 这里 获取更详细的信息). 若分配设备内存时未带有 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT 标志位,必须提供这些保证,应用程序必须从 区间的起始到最邻近的多个 VkPhysicalDeviceLimits::nonCoherentAtomSize聚集在一起,保证从区间的尾部到最邻近的多个 VkPhysicalDeviceLimits::nonCoherentAtomSize 聚集在一起。

当一块区域的设备内存被映射到主机端可访问,应用程序需要负责同步该区间的内存访问。

 

注意

应用程序开发者需要对本章Synchronization and Cache Control 描述的机制相当熟悉, 这对于维持按序访问内存来说极其重要。

正确使用

  • memory 必须未被映射过

  • offset 必须要被 memory 的大小要小

  • 若 size 不等于 VK_WHOLE_SIZE, size 必须大于 0

  • 若 size 不等于 VK_WHOLE_SIZEsize 必须小于等于 memory 减去 offset的结果的大小

  • memory 必须在创建时带有 内存类型 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT

Valid Usage (Implicit)

  • device must be a valid VkDevice handle

  • memory must be a valid VkDeviceMemory handle

  • flags must be 0

  • ppData must be a pointer to a pointer

  • memory must have been created, allocated, or retrieved from device

Host Synchronization

  • Host access to memory must be externally synchronized

Return Codes

Success

  • VK_SUCCESS

Failure

  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

  • VK_ERROR_MEMORY_MAP_FAILED

为了应用程序可以与非一致性内存分配一起工作,有两个命令可以使用: vkFlushMappedMemoryRanges 和 vkInvalidateMappedMemoryRanges

 

注意

若创建内存对象时带有VK_MEMORY_PROPERTY_HOST_COHERENT_BIT 参数, vkFlushMappedMemoryRanges 和 vkInvalidateMappedMemoryRanges 是没有必要的,且可能会有性能损失。

可调用如下命令来把CPU缓存刷新到非一致的内存区域中:

VkResult vkFlushMappedMemoryRanges(
    VkDevice                                    device,
    uint32_t                                    memoryRangeCount,
    const VkMappedMemoryRange*                  pMemoryRanges);
  • device 是拥有内存对象的逻辑设备。

  • memoryRangeCount 是 pMemoryRanges 数组的长度。

  • pMemoryRanges 是一个指向 VkMappedMemoryRange 类型数组的指针,描述了需要刷新的内存区域。

vkFlushMappedMemoryRanges 必须用于保证host端写入到非一致性内存的内容对于 device可见。 只能在host端写入到非一致性内存之后,且在会读取或写入这些内存的命令缓冲区被提交到队列之前,才可以被调用。

 

注意

取消非一致性内存映射并不意味着刷新被映射的内存, 没有被刷新的 host端写入的内容 可能对device不可见。

Valid Usage (Implicit)

  • device must be a valid VkDevice handle

  • pMemoryRanges must be a pointer to an array of memoryRangeCount valid VkMappedMemoryRange structures

  • memoryRangeCount must be greater than 0

Return Codes

Success

  • VK_SUCCESS

Failure

  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

可调用如下函数从host端cache使 非一致性内存无效:

VkResult vkInvalidateMappedMemoryRanges(
    VkDevice                                    device,
    uint32_t                                    memoryRangeCount,
    const VkMappedMemoryRange*                  pMemoryRanges);
  • device 是拥有内存范围的逻辑设备。

  • memoryRangeCount 是 pMemoryRanges 数组的长度。

  • pMemoryRanges 是一个指针,指向一个 VkMappedMemoryRange 数据结构的数组,描述了需要无效化的内存区间。

vkInvalidateMappedMemoryRanges must be used to guarantee that device writes to non-coherent memory are visible to the host. It must be called after command buffers that execute and flush (via memory barriers) the device writes have completed, and before the host will read or write any of those locations. If a range of non-coherent memory is written by the host and then invalidated without first being flushed, its contents are undefined.

 

注意

Mapping non-coherent memory does not implicitly invalidate the mapped memory, and device writes that have not been invalidated must be made visible before the host reads or overwrites them.

Valid Usage (Implicit)

  • device must be a valid VkDevice handle

  • pMemoryRanges must be a pointer to an array of memoryRangeCount valid VkMappedMemoryRange structures

  • memoryRangeCount must be greater than 0

Return Codes

Success

  • VK_SUCCESS

Failure

  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

VkMappedMemoryRange 类型数据结构定义如下:

typedef struct VkMappedMemoryRange {
    VkStructureType    sType;
    const void*        pNext;
    VkDeviceMemory     memory;
    VkDeviceSize       offset;
    VkDeviceSize       size;
} VkMappedMemoryRange;
  • sType 是数据结构的类型。

  • pNext 是 NULL 或者一个指向拓展特定的数据结构的指针。

  • memory 是这个区间所在的内存对象。

  • offset 是一个从内存对象的起始位置开始的,从0开始的偏移量。

  • size 要么是区间的大小,要么是 影响到 从 offset 到当前映射到分配的内存结束的区间的 VK_WHOLE_SIZE 。

正确使用

  • memory 当前必须已经被映射了

  • 若 size 和 VK_WHOLE_SIZE 不相等,offset 和 size 必须: 指定已经映射的内存 memory 之中的一段区间。

  • 若 size 和 VK_WHOLE_SIZE 相等, offset 必须: 和已经映射的内存的区间完全相同。

  • offset 必须: 是 VkPhysicalDeviceLimits::nonCoherentAtomSize 的倍数

  • 若 size和 VK_WHOLE_SIZE 不相等,size 必须: 是 VkPhysicalDeviceLimits::nonCoherentAtomSize 的倍数。

Valid Usage (Implicit)

  • sType must be VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE

  • pNext must be NULL

  • memory must be a valid VkDeviceMemory handle

 

editing-note

TODO (Tobias) - There’s a circular section reference between this next section and the synchronization section. The information is all covered by both places, but it seems a bit weird to have them reference each other. Not sure how to resolve it.

Host-visible memory types that advertise the VK_MEMORY_PROPERTY_HOST_COHERENT_BIT property still require memory barriers between host and device in order to be coherent, but do not require additional cache management operations to achieve coherency. For host writes to be seen by subsequent command buffer operations, a pipeline barrier from a source of VK_ACCESS_HOST_WRITE_BIT and VK_PIPELINE_STAGE_HOST_BIT to a destination of the relevant device pipeline stages and access types must be performed. Note that such a barrier is performed implicitly upon each command buffer submission, so an explicit barrier is only rarely needed (e.g. if a command buffer waits upon an event signaled by the host, where the host wrote some data after submission). A pipeline barrier is required to make writes visible to subsequent reads on the host.

应用程序若不在需要从host端访问内存对象,可调用如下命令来取消映射:

void vkUnmapMemory(
    VkDevice                                    device,
    VkDeviceMemory                              memory);
  • device 是拥有内存的逻辑设备。

  • memory 是将要被取消映射的内存对象。

正确使用

  • memory 在当前必须被映射过

Valid Usage (Implicit)

  • device must be a valid VkDevice handle

  • memory must be a valid VkDeviceMemory handle

  • memory must have been created, allocated, or retrieved from device

Host Synchronization

  • Host access to memory must be externally synchronized

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值