1. 程式人生 > >Vulkan Cookbook 第四章 5 建立影象

Vulkan Cookbook 第四章 5 建立影象

建立影象

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

影象表示可以具有一維、二維或三維的資料,並且可以具有額外的mipmap級別和圖層。影象資料的每個元素(紋理元素)也可以具有一個或多個樣本。

影象可用於許多不同的目的。我們可以將它們用作複製操作的資料來源。也可以通過描述符集將影象繫結到管線,並將它們用作紋理(類似於OpenGL)。可以渲染成影象,在這種情況下我們使用影象作為顏色或深度附件(渲染目標)。

我們在影象建立期間指定影象引數,例如大小、格式及其預期用途。

做好準備...

1.獲取我們要在其上建立影象的邏輯裝置控制代碼。將其儲存在名為logical_device的VkDevice型別變數中。
2.選擇影象型別(如果影象應具有一維、二維或三維)並使用適當的值初始化名為type的VkImageType型別變數。
3.選擇影象格式,每個影象元素應包含的元件數和位數。將格式儲存在名為format的VkFormat型別變數中。
4.選擇影象的大小(尺寸)並使用它來初始化名為size的VkExtent3D型別變數。
5.選擇應為影象定義的mipmap級別數量儲存在名為num_mipmaps的uint32_t型別變數中。
6.選擇應為影象定義的圖層數量,並將其儲存在名為num_layers的uint32_t型別變數中。如果影象將用作立方體貼圖,則圖層數量必須是6的倍數。
7.建立一個名為samples的VkSampleCountFlagBits型別的變數,並使用表示樣本數量的值對其進行初始化。
8.選擇預期的影象用法,在名為usage_scenarios的VkImageUsageFlags型別的變數中定義它們。
9.建立名為image_create_info的VkImageCreateInfo型別變數。為其成員賦值:
   ·sType為VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
    ·pNext為nullptr
    ·flags的話,如果影象應該用作立方體貼圖,請使用VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT值,否則使用0值。
    ·type為imageType
    ·format為format
    ·extent為size
    ·mipLevels為num_mipmaps
    ·arrayLayers為num_layers
    ·samples為samples
    ·tiling為VK_IMAGE_TILING_OPTIMAL
    ·usage為usage_scenarios
    ·sharingMode為VK_SHARING_MODE_EXCLUSIVE
    ·queueFamilyIndexCount為0
    ·pQueueFamilyIndices為nullptr
    ·initialLayout為VK_IMAGE_LAYOUT_UNDEFINED
10.建立一個名為image的VkImage型別變數。將建立影象控制代碼儲存其中。
11.呼叫vkCreateImage( logical_device, &image_create_info, nullptr, &image ),提供邏輯裝置控制代碼、指向image_create_info的指標、null值以及指向image變數的指標。
12.確保vkCreateImage呼叫返回的值等於VK_SUCCESS。

怎麼做...

當我們想要建立影象時,需要準備多個引數:影象的型別、尺寸(大小),組建的數量以及每個組建的位數(格式)。我們還需要知道影象是否包含mipmap或者它是否包含多個圖層(普通影象必須包含至少一個,而立方圖影象必須至少包含六個)。還必須考慮預期的使用場景,這些場景也是在影象建立過程中定義的。我們不能以一種在建立的過程中未定義的方式使用影象。

提示:影象只能用於建立期間指定的用途(目的)。

以下是可以使用影象的目的列表:
    ·VK_IMAGE_USAGE_TRANSFER_SRC_BIT指定影象可用作複製操作的資料來源
    ·VK_IMAGE_USAGE_TRANSFER_DST_BIT指定我們可以將資料賦值到影象
    ·VK_IMAGE_USAGE_SAMPLED_BIT表示我們可以從著色器內的影象中採集資料
    ·VK_IMAGE_USAGE_STORAGE_BIT指定影象可以用作著色器內的儲存影象
    ·VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT指定我們可以渲染到影象中(將其用作幀緩衝區中的顏色渲染目標/附件)
    ·VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT表示影象可以用做深度和/或模板緩衝區(作為幀緩衝區中的深度渲染目標/附件)
    ·VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT表示繫結的影象的記憶體將被懶惰的分配(按需)
    ·VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT指定影象可用作著色器內的輸入附件

不同的使用場景需要使用不同的影象佈局。這些更改(轉換)需使用影象記憶體屏障。但是在建立過程中,我們只能指定VK_IMAGE_LAYOUT_UNDEFINED (如果我們不關心初始化內容)或VK_IMAGE_LAYOUT_PREINITIALIZED(如果我們想通過對映主機可見記憶體來上傳資料),並且在實際使用之前總是需要轉換到另一個佈局。

譯者注:從上面的提示來理解用途是必須在建立期間指定的,但是這裡有一句這些更改(轉換)需使用影象記憶體屏障看樣子影象佈局是可以在之後使用過程中改變的,而用途不是,這裡很容易引起歧義,需要注意!

所有影象引數都通過VkImageCreateInfo型別的變數指定,如下所示:

VkImageCreateInfo image_create_info = { 
  VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
  nullptr,
  cubemap ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0u, 
  type,
  format,
  size,
  num_mipmaps,
  cubemap ? 6 * num_layers : num_layers, 
  samples,
  VK_IMAGE_TILING_OPTIMAL, 
  usage_scenarios, 
  VK_SHARING_MODE_EXCLUSIVE,
  0,
  nullptr,
  VK_IMAGE_LAYOUT_UNDEFINED,
};

當我們建立影象時,還需要指定平鋪(tiling)。它定義了影象的記憶體結構。有兩種可用的影象拼貼型別:線性和最佳。

當使用線性平鋪(linear tiling)時,顧名思義影象的資料以線性方式在記憶體中,類似於緩衝區或c/c++陣列。這准許我們對映影象的記憶體,並從應用程式中直接讀取或初始化它,因此我們知道記憶體是如何組織的。不幸的是,它限制我們將影象用於許多目的;例如,我們不能將影象用作深度紋理或立方體貼圖(某些驅動程式可能支援它,但規範並不要求它,一般來說我們不應該依賴它)。線性平鋪會降低我們應用的效能。

提示:為獲得最佳效能,簡易使用最佳螢幕建立影象。

具有最佳螢幕(optimal tiling)的影象可用於所有目的;他們也有更好的表現。但這需要權衡,我們不知道影象的記憶體是如何組織的。在下圖中,我們可以看到影象資料的示例及其內部結構:

每種型別的影象硬體都可以以對其最佳的不同方式儲存影象資料。因此我們無法對映影象的記憶體並直接從應用程式初始化或讀取它。在這種情況下,我們需要使用暫存資源(staging resources)。當準備好後,可以使用以下程式碼建立一個影象:

VkResult result = vkCreateImage( logical_device, &image_create_info, nullptr, &image ); 
if( VK_SUCCESS != result ) {
  std::cout << "Could not create an image." << std::endl;
  return false; 
}
return true;