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

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