Vulkan 圖像視圖
共 16155字,需瀏覽 33分鐘
·
2024-08-09 08:16
7. Vulkan 緩存
什么是 Vulkan 圖像視圖
Vulkan 圖像視圖(VkImageView)用于描述如何訪問 VkImage 對象以及訪問圖像的哪一部分。
圖像視圖定義了圖像的格式和訪問方式,它允許渲染管線與圖像進行交互,無論是作為紋理、顏色附件還是深度/模板附件。
在交換鏈中,我們需要為每個圖像創(chuàng)建一個基本的圖像視圖,以便將它們用作顏色附件。
VkImage 作為紋理采樣時,也必須要創(chuàng)建其對應(yīng)的圖像視圖來更新描述符集 (DescriptorSet)。
創(chuàng)建圖像視圖
我們通過函數(shù) vkCreateImageView 創(chuàng)建圖像視圖。
1// vkCreateImageView 函數(shù)用于創(chuàng)建圖像視圖
2VkResult vkCreateImageView(
3 VkDevice device, // Vulkan 邏輯設(shè)備的句柄,表示在哪個設(shè)備上創(chuàng)建圖像視圖
4 const VkImageViewCreateInfo* pCreateInfo, // 指向包含圖像視圖創(chuàng)建信息的 VkImageViewCreateInfo 結(jié)構(gòu)體的指針
5 const VkAllocationCallbacks* pAllocator, // 指向自定義分配函數(shù)的指針,可以為 nullptr 表示使用默認分配器
6 VkImageView* pView // 指向 VkImageView 變量的指針,用于存儲創(chuàng)建的圖像視圖句柄
7);
其中 VkImageViewCreateInfo 是一個包含圖像視圖創(chuàng)建信息的結(jié)構(gòu)體。
1typedef struct VkImageViewCreateInfo {
2VkStructureType sType; // 結(jié)構(gòu)體的類型,對于此結(jié)構(gòu)體應(yīng)為VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO
3const void* pNext; // 指向擴展特定數(shù)據(jù)的指針,對于核心Vulkan功能,通常為NULL
4VkImageViewCreateFlags flags; // 創(chuàng)建圖像視圖時使用的標(biāo)志位
5VkImage image; // 要創(chuàng)建視圖的圖像的句柄
6VkImageViewType viewType; // 圖像視圖的類型,決定了視圖是如何解釋圖像的
7VkFormat format; // 圖像數(shù)據(jù)的格式,定義了圖像數(shù)據(jù)的解釋方式
8VkComponentMapping components; // 用于在創(chuàng)建視圖時重新映射圖像的顏色分量
9VkImageSubresourceRange subresourceRange; // 定義了圖像視圖的子資源范圍,包括mipmap級別、數(shù)組層以及深度層的范圍
10} VkImageViewCreateInfo;
其中 VkImageViewType、VkComponentMapping、VkImageSubresourceRange 類型的屬性重點關(guān)注下。
VkImageViewType
VkImageViewType 指定了圖像視圖的類型。
1// VkImageViewType 是一個枚舉類型,指定了圖像視圖的類型。
2typedef enum VkImageViewType {
3 VK_IMAGE_VIEW_TYPE_1D = 0, // 一維圖像視圖
4 VK_IMAGE_VIEW_TYPE_2D = 1, // 二維圖像視圖
5 VK_IMAGE_VIEW_TYPE_3D = 2, // 三維圖像視圖
6 VK_IMAGE_VIEW_TYPE_CUBE = 3, // 立方體貼圖視圖(六個面)
7 VK_IMAGE_VIEW_TYPE_1D_ARRAY = 4, // 一維圖像數(shù)組
8 VK_IMAGE_VIEW_TYPE_2D_ARRAY = 5, // 二維圖像數(shù)組
9 VK_IMAGE_VIEW_TYPE_CUBE_ARRAY = 6 // 立方體貼圖數(shù)組(六個面 * 圖層數(shù))
10} VkImageViewType;
VkComponentMapping
VkComponentMapping 用于指定如何從源圖像中的顏色分量映射到目標(biāo)圖像視圖的顏色分量。
通過 VkComponentMapping 類型的屬性(components) 可以靈活地控制圖像視圖中每個顏色分量的來源,這對于圖像處理非常有用,例如轉(zhuǎn)換圖像格式、調(diào)整顏色通道等。
默認情況下,我們將每個分量設(shè)置為 VK_COMPONENT_SWIZZLE_IDENTITY,這意味著它們將直接從源圖像中取值。
1// VkComponentMapping 結(jié)構(gòu)體定義了圖像視圖中每個顏色分量的來源。
2typedef struct VkComponentMapping {
3 VkComponentSwizzle r; // R 分量的來源
4 VkComponentSwizzle g; // G 分量的來源
5 VkComponentSwizzle b; // B 分量的來源
6 VkComponentSwizzle a; // A 分量的來源
7} VkComponentMapping;
8
9// VkComponentSwizzle 是一個枚舉類型,定義了分量的來源。
10typedef enum VkComponentSwizzle {
11 VK_COMPONENT_SWIZZLE_IDENTITY = 0, // 使用原始分量
12 VK_COMPONENT_SWIZZLE_ZERO = 1, // 使用零值
13 VK_COMPONENT_SWIZZLE_ONE = 2, // 使用一值
14 VK_COMPONENT_SWIZZLE_R = 100, // 使用 R 分量
15 VK_COMPONENT_SWIZZLE_G = 101, // 使用 G 分量
16 VK_COMPONENT_SWIZZLE_B = 102, // 使用 B 分量
17 VK_COMPONENT_SWIZZLE_A = 103 // 使用 A 分量
18} VkComponentSwizzle;
VkImageSubresourceRange
VkImageSubresourceRange 允許你選擇圖像的哪些層面和 mip 級別應(yīng)該被包括在圖像視圖中。
1// VkImageSubresourceRange 結(jié)構(gòu)體定義了圖像視圖應(yīng)覆蓋的圖像子資源范圍。
2typedef struct VkImageSubresourceRange {
3 VkImageAspectFlags aspectMask; // 需要包括的圖像方面
4 uint32_t baseMipLevel; // mip 級別的起始級別
5 uint32_t levelCount; // mip 級別的數(shù)量
6 uint32_t baseArrayLayer; // 數(shù)組層的起始索引
7 uint32_t layerCount; // 數(shù)組層數(shù)量
8} VkImageSubresourceRange;
aspectMask 這個屬性比較難理解,它用于指定需要包括在圖像視圖中的圖像方面。
例如,如果圖像有深度和/或模板信息,你可以選擇只包括顏色方面 (VK_IMAGE_ASPECT_COLOR_BIT),或者包括深度方面 (VK_IMAGE_ASPECT_DEPTH_BIT) 和/或模板方面 (VK_IMAGE_ASPECT_STENCIL_BIT)。
示例代碼
1// 定義 VkImageCreateInfo 結(jié)構(gòu)體并初始化
2VkImageCreateInfo imageInfo = {};
3imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; // 結(jié)構(gòu)體類型
4imageInfo.pNext = nullptr; // 指向擴展信息的指針
5imageInfo.flags = 0; // 圖像創(chuàng)建標(biāo)志,當(dāng)前必須為 0
6imageInfo.imageType = VK_IMAGE_TYPE_2D; // 圖像類型為 2D
7imageInfo.format = VK_FORMAT_R8G8B8A8_SRGB; // 圖像格式為 sRGB
8imageInfo.extent.width = texWidth; // 圖像寬度
9imageInfo.extent.height = texHeight; // 圖像高度
10imageInfo.extent.depth = 1; // 圖像深度(對于 2D 圖像為 1)
11imageInfo.mipLevels = 1; // MIP 級別數(shù)量
12imageInfo.arrayLayers = 1; // 圖像數(shù)組層數(shù)
13imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; // 多重采樣數(shù)量(1 表示不使用多重采樣)
14imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; // 圖像數(shù)據(jù)的存儲方式(優(yōu)化存儲)
15imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; // 圖像用途(作為傳輸目標(biāo)和采樣器)
16imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; // 共享模式(獨占模式)
17imageInfo.queueFamilyIndexCount = 0; // 使用隊列族索引的數(shù)量
18imageInfo.pQueueFamilyIndices = &queueFamilyIndex; // 隊列族索引的指針
19imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // 圖像的初始布局(未定義)
20
21VkImage textureImage; // 定義 VkImage 變量
22// 創(chuàng)建圖像
23if (vkCreateImage(device, &imageInfo, nullptr, &textureImage) != VK_SUCCESS) {
24 throw std::runtime_error("failed to create texture image!"); // 如果創(chuàng)建圖像失敗,拋出異常
25}
26
27// 獲取圖像的內(nèi)存需求
28VkMemoryRequirements memRequirements;
29vkGetImageMemoryRequirements(device, textureImage, &memRequirements);
30
31// 創(chuàng)建 VkMemoryAllocateInfo 結(jié)構(gòu)體并初始化
32VkMemoryAllocateInfo allocInfo = {};
33allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; // 結(jié)構(gòu)體類型
34allocInfo.allocationSize = memRequirements.size; // 所需內(nèi)存大小
35allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits,
36 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); // 內(nèi)存類型索引
37
38VkDeviceMemory textureImageMemory; // 定義 VkDeviceMemory 變量
39// 分配內(nèi)存
40if (vkAllocateMemory(device, &allocInfo, nullptr, &textureImageMemory) != VK_SUCCESS) {
41 throw std::runtime_error("failed to allocate texture image memory!"); // 如果分配內(nèi)存失敗,拋出異常
42}
43
44// 將內(nèi)存綁定到圖像
45vkBindImageMemory(device, textureImage, textureImageMemory, 0);
46
47// 定義 VkImageViewCreateInfo 結(jié)構(gòu)體并初始化
48VkImageViewCreateInfo viewInfo = {};
49viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; // 結(jié)構(gòu)體類型
50viewInfo.pNext = nullptr; // 指向擴展信息的指針
51viewInfo.flags = 0; // 圖像視圖創(chuàng)建標(biāo)志
52viewInfo.image = textureImage; // 要創(chuàng)建視圖的圖像句柄
53viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; // 圖像視圖類型為 2D
54viewInfo.format = VK_FORMAT_R8G8B8A8_UNORM; // 圖像視圖的格式
55viewInfo.components.r = VK_COMPONENT_SWIZZLE_R; // R 分量映射
56viewInfo.components.g = VK_COMPONENT_SWIZZLE_G; // G 分量映射
57viewInfo.components.b = VK_COMPONENT_SWIZZLE_B; // B 分量映射
58viewInfo.components.a = VK_COMPONENT_SWIZZLE_A; // A 分量映射
59viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; // 視圖的子資源范圍(顏色部分)
60viewInfo.subresourceRange.baseMipLevel = 0; // 基礎(chǔ) MIP 級別
61viewInfo.subresourceRange.levelCount = 1; // MIP 級別數(shù)量
62viewInfo.subresourceRange.baseArrayLayer = 0; // 基礎(chǔ)數(shù)組層
63viewInfo.subresourceRange.layerCount = 1; // 數(shù)組層數(shù)量
64
65VkImageView textureImageView; // 定義 VkImageView 變量
66// 創(chuàng)建圖像視圖
67if (vkCreateImageView(device, &viewInfo, nullptr, &textureImageView) != VK_SUCCESS) {
68 throw std::runtime_error("failed to create texture image view!"); // 如果創(chuàng)建視圖失敗,拋出異常
69}
70
71// Vulkan 編程...
72
73// 使用完成后銷毀資源
74vkDestroyImageView(device, textureImageView, nullptr); // 銷毀圖像視圖
75vkDestroyImage(device, textureImage, nullptr); // 銷毀圖像
76vkFreeMemory(device, textureImageMemory, nullptr); // 釋放圖像內(nèi)存
-- END --
進技術(shù)交流群,掃碼添加我的微信:Byte-Flow
獲取相關(guān)資料和源碼
學(xué)習(xí)音視頻、OpenGL ES、Vulkan 、Metal、圖像濾鏡、視頻特效及相關(guān)渲染技術(shù)的付費社群,面試指導(dǎo),1v1 簡歷服務(wù),職業(yè)規(guī)劃。
我的付費社群
項目疑難問題解答、大廠內(nèi)部推薦、面試指導(dǎo)、簡歷指導(dǎo)、代碼指導(dǎo)、offer 選擇建議、學(xué)習(xí)路線規(guī)劃,可以點擊找我一對一解答。
