1. 程式人生 > >Vulkan Cookbook 第四章 14 將資料從影象複製到緩衝區

Vulkan Cookbook 第四章 14 將資料從影象複製到緩衝區

將資料從影象複製到緩衝區

譯者注:示例程式碼點選此處

在Vulkan中,我們不僅可以把資料從緩衝區傳輸到影象,還可以將資料從影象複製到緩衝區。繫結到它們的記憶體物件的屬性是什麼並不重要。但是資料複製操作是更新無法對映的裝置本地記憶體的唯一方法。

怎麼做...

1.獲取命令緩衝區的控制代碼並將其儲存在名為command_buffer的VkCommandBuffer型別變數中。確保命令緩衝區已處於記錄狀態(請參閱第3章,命令緩衝區和同步中的開始命令緩衝區記錄操作)。
2.獲取將複製資料的影象。將其控制代碼儲存在名為source_image的VkImage型別變數中。
3.準備源影象的當前記憶體佈局。初始化名為image_layout的VkImageLayout型別變數。
4.獲取將要複製資料的緩衝區。儲存在名為destination_buffer的VkBuffer型別的變數中準備其控制代碼。
5.建立名為regions的std::vector<VkBufferImageCopy> 型別的變數。對每個成員指定以下值:
    ·bufferOffset為從緩衝區記憶體開頭的偏移量。
    ·bufferRowLength表示緩衝區單行的資料長度,如果資料緊密打包(根據目標影象大小)則為0值。
    ·bufferImageHeight表示儲存在緩衝區中的虛構影象的高度(行數),如果緩衝區的資料緊密打包(根據目標影象大小)則0值。
    ·使用以下值初始化imageSubresource成員:
        ·aspectMask為影象方面(顏色、深度或模板)
        ·mipmap為mipmap級別的編號(索引)
        ·baseArrayLayer為第一個陣列層的編號
        ·layerCount為複製的陣列層數
    ·imageOffset為影象子區域的初始化偏移(以紋素為單位),從中讀取資料並將其複製到緩衝區。
    ·imageExtent為影象的大小(尺寸)。
6.呼叫vkCmdCopyImageToBuffer(command_buffer,source_image,image_layout,destination_buffer, static_cast<uint32_t>(regions.size()), &regions[0] ),使用command_buffer、source_image、image_layout、destination_buffer變數,regions向量中的元素數量以及指向其第一個元素的指標。

這個怎麼運作...

從影象到緩衝區複製資料是一種記錄到緩衝區的操作,如下所示:

if( regions.size() > 0 ) { 
  vkCmdCopyImageToBuffer( command_buffer, source_image, image_layout, destination_buffer, static_cast<uint32_t>(regions.size()), &regions[0] ); 
}

命令緩衝區必須已處於記錄狀態。

要正確複製資料,我們需要提供多個引數來定義資料來源和資料複製的目標。這些引數包括x、y和z維度的影象原點(從紋理的左上角)偏移,mipmap級別和從中複製資料的基礎陣列層以及層數將成為資料的來源。影象尺寸也是必須的。

對於目標緩衝區,我們指定一個記憶體偏移量(從緩衝區記憶體的開頭),資料行的長度和緩衝區中資料的高度。我們還可以為行長度和高度提供零,這意味著複製到緩衝區的資料將被緊密打包並且將對應於原影象的尺寸。

前面的引數是使用VkBufferImageCopy元素陣列指定的,類似於將資料從緩衝區複製到影象,如將資料從緩衝區複製到影象內容中所述。我們可以提供許多區域並複製不連續的記憶體範圍作為一個複製操作的一部分。

提示:必須使用VK_BUFFER_USAGE_TRANSFER_SRC_BIT用法建立用於複製資料的源影象。在傳輸操作之前,我們還需要將影象的佈局轉換為VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL。
          必須使用VK_BUFFER_USAGE_TRANSFER_DST_BIT用法建立可以複製資料的目標緩衝區。

在我們從影象中複製資料之前,應該設定一個記憶體屏障,並將影象的佈局從當前使用的佈局更改為VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL佈局。我們還應該將記憶體訪問的型別從目前發生的內容更改為VK_ACCESS_TRANSFER_READ_BIT。在完成從影象複製資料後,如果從現在開始將其用於其他目的。也應該設定屏障。這次我們應該將記憶體訪問型別從VK_ACCESS_TRANSFER_READ_BIT更改為與使用映像的目的對應的訪問型別。同時應該將佈局從VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL轉換為與影象的下一次使用相容的佈局(請參閱設定影象記憶體屏障內容)。沒有這些屏障,不僅可能以錯誤的方式執行資料傳輸操作,而且稍後的命令可能在傳輸完成之前覆蓋影象內容。

應該為緩衝區設定類似的屏障(但它們可以是同一個管線屏障的一部分)。如果之前緩衝區用於其他目的,我們應該在傳輸操作之前將記憶體訪問許可權更改為VK_ACCESS_TRANSFER_WRITE_BIT,如設定緩衝區記憶體屏障內容。