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;